[python]從蛇形打印矩陣說開去

手撕題常客,不是很難,但是思路比較多。

題目

給出一個n×nn\times n數組,按照回字形(“向右、向下、向左、向上”循環)打印,例如:

輸入n=3n=3,即數組:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]

蛇形輸出結果:
[1, 2, 3, 6, 9, 8, 7, 4, 5]

思路

1.方向、邊界與修改

這是比較直接的思路,給定一個方向d,分別指示下一步遊標(i,j)要移動的量,並給出一個邊界,移動到觸碰邊界時修改方向和邊界的值。

  • 該方法較爲常規,寫得不規範的話容易數組越界。

詳細代碼略,只給出構建原 n×nn\times n 矩陣的代碼以供下一步使用。

# 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.尋找規律

  1. 向當前一個方向移動的最大步數記爲next_step
  2. next_step符合規律n,n1,n1,n2,n2...1,1n,n-1,n-1,n-2,n-2...1,1
  3. 憑藉這個規律可以直接替換上個方法中的邊界修改和判定,減少因編碼不規範而導致的越界可能性

讓我們來構建這樣一個數列生成器:

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:當非正方形矩陣時

若變爲n×mn\times m矩陣,其實差別不大,生成器的序列實際上變爲兩個軌道的插入集。
如當n=3,m=4n=3,m=4:

  1. 橫向最大輸出步數符合數列4,3,2,14,3,2,1,即m,m1,m2,...,1m,m-1,m-2,...,1
  2. 縱向最大輸出步數符合數列2,12,1,即n1,n2,...1n-1,n-2,...1
  3. 先取橫向步數,再取縱向步數,交替取值,直至出現0(0不可取得)。
  4. 例如當n=3,m=4n=3,m=4,數列爲:4,2,3,1,24,2,3,1,2

修改【思路 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章