手撕題常客,不是很難,但是思路比較多。
題目
給出一個數組,按照回字形(“向右、向下、向左、向上”循環)打印,例如:
輸入,即數組:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]蛇形輸出結果:
[1, 2, 3, 6, 9, 8, 7, 4, 5]
思路
1.方向、邊界與修改
這是比較直接的思路,給定一個方向d
,分別指示下一步遊標(i,j)
要移動的量,並給出一個邊界,移動到觸碰邊界時修改方向和邊界的值。
- 該方法較爲常規,寫得不規範的話容易數組越界。
詳細代碼略,只給出構建原 矩陣的代碼以供下一步使用。
# prepare-origin matrix-data
n = 4 # size of matirx, for example, which is `4x4`
a = [[(i+1)+j*n for i in range(n)] for j in range(n)]
for line in a:
print(line)
2.尋找規律
- 向當前一個方向移動的最大步數記爲
next_step
- 則
next_step
符合規律。 - 憑藉這個規律可以直接替換上個方法中的邊界修改和判定,減少因編碼不規範而導致的越界可能性。
讓我們來構建這樣一個數列生成器:
def gen(n):
# build the step-swquence: [n, n-1, n-1, n-2, n-2 ... 1, 1]
# when yeile 0, matrix has been iterated
top = n
first = False # only output first number?
while True:
top = top-1 if first else top
yield top
first = not first
則解法爲:
# -------alg begin------- #
g = gen(n)
d = [(0, 1), (1, 0), (0, -1), (-1, 0)] # direction: to right, down, left, up
i, j= (0, 0) # pos-curse
index = 0 # control the direction to move
next_step, step = next(g), 0
result = []
while next_step > 0:
# save print value
result.append(a[i][j])
step += 1 # add move-action counters
if step >= next_step: # touch the boundary
# modify drection-index
index = (index+1)%4
# modify next-round-steps to move, reset step-counter
next_step, step = next(g), 0
# move pos-curse by drection-index
i += d[index][0]
j += d[index][1]
print("蛇形輸出結果:", result)
3.完全使用規律法進行輸出
如果矩陣的值完全按照順序遞增,那麼:
- 很顯然,從左向右時
j++
,從上向下i+=n
,從左向右時j--
,從上向下i-=n
。在上一個思路的基礎上,可以更快地實現代碼。
g = gen(n)
d = [1, n, -1, -n] # difference value: to right, down, left, up
a0 = a[0][0]-1 # matrix's value starts from 1
index = 0 # control the direction to move
next_step, step = next(g), 0
result = []
while next_step > 0: # b[0]<=i<=b[2] and b[3]<=j<=b[1]:
a0 = a0 + d[index]
result.append(a0)
step += 1
if step >= next_step: # touch the boundary
# modify drection-index
index = (index+1)%4
# modify next-round-steps to move
next_step, step = next(g), 0
print("蛇形輸出結果:", result)
SP:當非正方形矩陣時
若變爲矩陣,其實差別不大,生成器的序列實際上變爲兩個軌道的插入集。
如當:
- 橫向最大輸出步數符合數列,即。
- 縱向最大輸出步數符合數列,即
- 先取橫向步數,再取縱向步數,交替取值,直至出現0(0不可取得)。
- 例如當,數列爲:
修改【思路 2】中的生成器並直接使用【思路 3】(或【思路2】,若矩陣的值非遞增的話) 的算法框架可以得到非正方形矩陣下的解題代碼:
def gen(n, m):
# build the step-swquence: [m, n-1, m-1, n-2, m-2 ... 1]
top_n, top_m = n-1, m
first = True # first time to output?
while True:
if first:
yield top_m
top_m -= 1
else:
yield top_n
top_n -= 1
first = not first