Spiral Matrix - Leetcode 54 - Arrays & Strings (Python)

preview_player
Показать описание


Please check my playlists for free DSA problem solutions:

My Favorite Courses:

Data Structures & Algorithms:

Python:

Web Dev / Full Stack:

Cloud Development:

Game Development:

SQL & Data Science:

Machine Learning & AI:
Рекомендации по теме
Комментарии
Автор

Master Data Structures & Algorithms For FREE at AlgoMap.io!

GregHogg
Автор

Simpler solution
l, r, t, b, res = 0, len(matrix[0]), 0, len(matrix), []
while l < r and t < b:
for j in range(l, r):
res.append(matrix[t][j])
t += 1
for i in range(t, b):
res.append(matrix[i][r - 1])
r -= 1
if not (l < r and t < b): break
for j in range(r - 1, l - 1, -1):
res.append(matrix[b - 1][j])
b -= 1
for i in range(b - 1, t - 1, -1):
res.append(matrix[i][l])
l += 1
return res

ngneerin
Автор

This is porbably the most intuitive solution I found. Thanks Gregg

Chibabachacho
Автор

I am happy I thought about the same solution as you but made some mistakes while executing. Some mistakes I did were,
1. Not doing one direction per iteration of the outer while loop. I basically tried to do all the directions one after the other
2. starting left pointer from 0.

Thanks for all the amazing work you are doing and helping thousands of engineers

dotjs
Автор

dequeue/shift the first row -> rotate matrix by 90° -> repeat

earldominic
Автор

Thanks, for the video. I think my solution is harder to understand but has less coding space so here it is:

class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:

n, m = len(matrix), len(matrix[0])
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
x, y = 0, -1
direction = 0
res = []
coordinates = []
while len(res) != n * m:
i, j = directions[direction]
if (0 <= x + i < n and 0 <= y + j < m and
(x + i, y + j) not in coordinates):
x += i
y += j
res.append(matrix[x][y])
coordinates.append((x, y))
else:
direction = (direction + 1) % 4

return res

bekzodhalilov
Автор

Here is my solution to this problem. It utilises the fact you can just take the outward (perimeter) spiral each time and then select the inner (m-2) x (n-2) elements each time (the inner central matrix) until you run out of elements.

m, n = len(matrix), len(matrix[0])
answer = []

def getPerimeter(mat):
if len(mat) == 1:
return mat[0]
if len(mat[0]) == 1:
return [i[0] for i in mat]
return mat[0] + [i[-1] for i in mat[1:-1]] + mat[-1][::-1] + [i[0] for i in mat[1:-1][::-1]]

while len(answer) != (m * n):
answer += getPerimeter(matrix)
matrix = [row[1:-1] for row in matrix[1:-1]]

return answer

chandlerkenworthy
Автор

My solution - Add the popped elements (from matrix) to result array over one loop, Recur until matrix is empty
Step 1 - Pop the first row and add to the result array
Within the try / catch block
Step 2 - Pop the elements from rightmost column and add to the result array
Step 3 - Pop the last row in reverse and add to the result array
Step 4 - Pop the elements from leftmost column and add to the result array
Step 5 - Recur until matix is empty - return result + spiralOrder(matrix)
Catch IndexError (which means matrix is empty) and return result

JoeTan-nqfq
Автор

Another solution would be to cut off the first row of the matrix and then rotate it to the left. Repeat until only one element remains. It's not faster, however.

carnagen
Автор

I added comments because the code seems complicated without them.

import enum

# direction constants
class Direction(enum.Enum):
RIGHT = enum.auto()
DOWN = enum.auto()
LEFT = enum.auto()
UP = enum.auto()

class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
# output array
arr = []

# rows and columns determine bounding box indexes
rows = len(matrix)
cols = len(matrix[0])

# bounding box indexes
top, left, right, bottom = 0, 0, cols - 1, rows - 1

# starting traversal direction
direction = Direction.RIGHT

# expected number of total elements
total = rows * cols

# once we have rows*cols elements, we must have visited everyone
while len(arr) != total:
# what direction is our spiral traveling
match direction:
case Direction.RIGHT:
# add everything in the top row between the left/right walls
for i in range(left, right + 1):
arr.append(matrix[top][i])

# move bounding box down and update direction
top += 1
direction = Direction.DOWN
case Direction.DOWN:
# top to bottom

# add everything in the right column between the top/bottom walls
for i in range(top, bottom + 1):
arr.append(matrix[i][right])

# move bounding box left and update direction
right -= 1
direction = Direction.LEFT
case Direction.LEFT:
# right to left

# add elements in the bottom row from right->left
for i in range(right, left - 1, -1):
arr.append(matrix[bottom][i])

# move bounding box up and update direction
bottom -= 1
direction = Direction.UP
case Direction.UP:
# bottom to top

# add elements in the left column from bottom->top
for i in range(bottom, top - 1, -1):
arr.append(matrix[i][left])

# move bounding box right and update direction
left += 1
direction = Direction.RIGHT

return arr

jdratlif
Автор

came up with a similar idea but couldn't fully code it out. Lord I hope I don't come across this during an interview

Powaup
Автор

this oneliner is not my solutiion, but works like a charm:
return matrix and [*matrix.pop(0)] +

barmalini
Автор

function spiralOrder(matrix: number[][]): number[] {
let startCol = 0;
let endCol = matrix[0].length - 1;
let startRow = 0;
let endRow = matrix.length - 1;
const result = [];
console.log(startCol, endCol, startRow, endRow)

while (startCol <= endCol && startRow <= endRow) {
for (let i = startCol; i <= endCol; i++) {

}
startRow++;

for (let i = startRow; i <= endRow; i++) {

}
endCol--;

if (startRow <= endRow) {
for (let i = endCol; i >= startCol; i--) {

}
endRow--;
}

if (startCol <= endCol) {
for (let i = endRow; i >= startRow; i--) {

}
startCol++;
}
}

return result;
};
I solved it using ts code and in my opinion it is easier to understand. Hope it helps you!

phuothuynhvan
Автор

Hlo greg what are your thoughts on my code using java
static List<Integer> spiralOrder(int[][] m) {
List<Integer> list = new ArrayList<Integer>();
int size = 0;
if(m.length %2 == 0)
size = m.length/2;
else
size = m.length/2 + 1;

for(int i=0; i<size; i++) {
int k = i, j = i;

while(j<m[i].length-i && k < m.length-i) {
list.add(m[k][j]);
if(j<m[i].length - 1 - i)

else

}

k--;j--;

while(j >= i && k > i) {
list.add(m[k][j]);
if(j > i)

else

}
}
return list;
}

vasu_
visit shbcf.ru