Skip to content

Commit 1780a9e

Browse files
My solution for 885
1 parent 830e03d commit 1780a9e

File tree

1 file changed

+85
-2
lines changed

1 file changed

+85
-2
lines changed

problems/885/jeremymanning.md

+85-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,94 @@
11
# [Problem 885: Spiral Matrix III](https://leetcode.com/problems/spiral-matrix-iii/description/?envType=daily-question)
22

33
## Initial thoughts (stream-of-consciousness)
4+
- I'm seeing a few parts of this problem:
5+
- First, we need to have an outer while loop (until all cells are visited) where we cycle through right, down, left, and up moves
6+
- Moving right entails adding 1 to the column; down means adding 1 to the row; left means subtracting 1 from the column; up means subtracting 1 from the row
7+
- We need to keep track of the max/min rows and columns we've visited. As we're moving in some direction, we want to keep moving until we hit either:
8+
- One more than the current max (or min) visited (in which case we should now updated the max/min values as needed) OR
9+
- The outer bounds of the matrix
10+
- In some cases (e.g., if some arm of the spiral occurs outside of the bounds of the matrix) we might not add *any* new cells to the path in a given direction. In that case we just skip to the endpoint and take one step along the next direction in the spiral.
11+
- To keep track of visited locations we can use a list of coordinates, `path`. This is what we'll return at the end.
12+
- To keep track of the outer bounds, we can use four variables-- `min_row`, `max_row`, `min_col`, and `max_col`. Initially we can set these to the corresponding values in `rStart` and `cStart`.
413

514
## Refining the problem, round 2 thoughts
15+
- The one tricky piece is what happens when we're outside of the bounds of the matrix.
16+
- The "efficient" solution would be to skip ahead to the end of that leg of the path.
17+
- If we're moving *right* (but above the top or below the bottom of the matrix), then the next coordinate will be `[max_row, max_col]` (and so on for the other directions)
18+
- But actually, this potentially leads to another tricky scenario: what if the *next* move (e.g., *down* after we've finished moving right) is *also* outside of the bounds of the matrix?
19+
- So instead, I think we should do something easier:
20+
- If we're ever making a move that's outside of the matrix, we'll follow the same logic in making right/down/left/up moves as always (though not updating the outer bounds if we're already outside of the matrix's limits)-- but we should only append a given "location" to `path` if it falls within the bounds of the matrix-- i.e., for location `[x, y]` we should only append it to `path` if `(0 <= x < rows) and (0 <= y < cols)`.
21+
- This will be a little less efficient (we might need to temporarily store in memory a set of up to 102 locations, e.g., if we're dealing with a matrix of size 100 along some dimension and we're outside of the bounds at both ends along that dimension) but it's not too bad given the matrix sizes we're dealing with, and it'll make the code much simpler.
22+
- I think I should also write functions `moveRight(x, y)`, `moveLeft(x, y)`, `moveUp(x, y)`, and `moveDown(x, y)` to return a list of moves along the given direction, given the starting location `[x, y]`. (These will each need to reference the "bounds" variables.)
23+
- Then once we get each move, we can just extend path as follows: `path.extend([[x, y] for x, y in moves if (0 <= x < rows) and (0 <= y < cols)])`. And if the last position (`moves[-1]`) is within the bounds of the matrix along the relevant direction, we'll need to update the relevant bound accordingly.
24+
- There are a few pieces to this one, but I think it's straightforward. I'll move on to implementing this now.
25+
- Note: actually, rather than `x` and `y`, let's use `r` (for row) and `c` (for column)...otherwise I think the right/left/up/down functions' notations will get confusing to read. But functionally they'll be the same as above.
626

727
## Attempted solution(s)
828
```python
9-
class Solution: # paste your code here!
10-
...
29+
class Solution:
30+
def spiralMatrixIII(self, rows: int, cols: int, rStart: int, cStart: int) -> List[List[int]]:
31+
min_row, max_row = rStart, rStart
32+
min_col, max_col = cStart, cStart
33+
34+
def moveRight(pos):
35+
r, c = pos
36+
return [[r, x] for x in range(c + 1, max_col + 2)]
37+
38+
def moveLeft(pos):
39+
r, c = pos
40+
return [[r, x] for x in range(c - 1, min_col - 2, -1)]
41+
42+
def moveUp(pos):
43+
r, c = pos
44+
return [[y, c] for y in range(r - 1, min_row - 2, -1)]
45+
46+
def moveDown(pos):
47+
r, c = pos
48+
return [[y, c] for y in range(r + 1, max_row + 2)]
49+
50+
def inBounds(pos):
51+
r, c = pos
52+
return (0 <= r < rows) and (0 <= c < cols)
53+
54+
path = [[rStart, cStart]]
55+
pos = [rStart, cStart]
56+
while len(path) < rows * cols:
57+
# move right
58+
moves = moveRight(pos)
59+
path.extend([m for m in moves if inBounds(m)])
60+
pos = moves[-1]
61+
max_col = max(min(cols + 1, pos[1]), max_col)
62+
63+
# move down
64+
moves = moveDown(pos)
65+
path.extend([m for m in moves if inBounds(m)])
66+
pos = moves[-1]
67+
max_row = max(min(rows + 1, pos[0]), max_row)
68+
69+
# move left
70+
moves = moveLeft(pos)
71+
path.extend([m for m in moves if inBounds(m)])
72+
pos = moves[-1]
73+
min_col = min(max(0, pos[1]), min_col)
74+
75+
# move up
76+
moves = moveUp(pos)
77+
path.extend([m for m in moves if inBounds(m)])
78+
pos = moves[-1]
79+
min_row = min(max(0, pos[0]), min_row)
80+
81+
return path
1182
```
83+
- Given test cases pass
84+
- Let's try some more:
85+
- `rows = 100, cols = 100, rStart = 50, cStart = 50`: pass
86+
- `rows = 100, cols = 100, rStart = 99, cStart = 50`: pass
87+
- `rows = 100, cols = 100, rStart = 99, cStart = 0`: pass
88+
- `rows = 1, cols = 100, rStart = 0, cStart = 99`: pass
89+
- Ok...let's submit...
90+
91+
![Screenshot 2024-08-07 at 11 55 04 PM](https://github.com/user-attachments/assets/fb2ad127-a514-4737-ae78-b7392b4a8250)
92+
93+
Solved!
94+

0 commit comments

Comments
 (0)