こんにちは
今回の学びは
・方向の情報はtupleで方向差分を保持するのがスマート
問題は。。。
(時間配分は5分問題理解 10分検討 10分実装 20分振り返り の一文45分構成)
まずは入出力をしっかりおさえましょう。
これ以外に難しですよねー
パッと思いつくのはvisittedみたいなmatrix用意して、すでに訪れた場所には行かずに、
さらに方向を記憶して右下左上の順番に循環していく方法。
今回はこれで実装しました
というもの、以前この問題か似た問題を解いた時にout of indexを壁みたいに捉えて、m * nの一回り大きくした(m+1) * (n+1)を
こしらえて、壁は-1で表現しようみたいにすると
実は実装が難しく、すごく苦労するか断念することになります。ので、最初のシンプルな考えで実装していきます
実装前後でこれは毎回書きましょう。timespace analysis (時間とスペースの分析)は O(N) with space O(N) for visitted
といったところです
実装の途中で 方向の情報はtupleで方向差分を保持するのがスマート
ということに気づきました
# 方向を以下のようなtupleで表現
direction_set = ((0, 1), (1, 0), (0, -1), (-1, 0))
def change_direction(direction):
direction += 1
if direction == 4:
direction = 0
return direction
# そしてこうして使う
arrow = direction_set[direction]
実際の実装はこちら
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
if len(matrix) == 0: return matrix
if len(matrix[0]) == 0: return []
m = len(matrix)
n = len(matrix[0])
visitted = [[0] * n for _ in range(m)]
# right, down , left , up
direction_set = ((0, 1), (1, 0), (0, -1), (-1, 0))
def change_direction(direction):
direction += 1
if direction == 4:
direction = 0
return direction
def get_next(i, j, direction):
arrow = direction_set[direction]
i_ = i + arrow[0]
j_ = j + arrow[1]
if i_ < 0 or j_ < 0 or i_ >= m or j_ >= n or visitted[i_][j_] == 1:
direction = change_direction(direction)
arrow = direction_set[direction]
i_ = i + arrow[0]
j_ = j + arrow[1]
if i_ < 0 or j_ < 0 or i_ >= m or j_ >= n or visitted[i_][j_] == 1:
return (None, i_, j_, direction) # end
else:
visitted[i_][j_] = 1
return (matrix[i_][j_], i_, j_, direction)
else:
visitted[i_][j_] = 1
return (matrix[i_][j_], i_, j_, direction)
path = []
i = 0
j = -1
direction = 0
for _ in range(m*n):
(value, i, j, direction) = get_next(i, j, direction)
if value == None: break
path.append(value)
return path
実装後です。timespace analysis (時間とスペースの分析)は O(n) with space O(N)
実装は長いですが動きます。

他の人の解答も参考にしておきましょう。
。。。
まとめ
・方向の情報はtupleで方向差分を保持するのがスマート
以上です