iT邦幫忙

0

方向向量法走訪N維陣列

動機

在 leetcode 解Spiral Matrix ([1]) 時,看了網上分享的解法,多半是考慮各種邊界情況搭配 if-else 做判斷,經過嘗試後,我找到一種較為簡潔的方法,以下用實際題目進行說明。

題目大意

給定 mxn 矩陣,希望我們從第一個元素出發,順時針方向螺旋向內移動,並依序返回途中經過的數值。

思路

因為移動模式固定為 右->下->左->上->右->下...,而改變方向的時機為碰到邊界時。
設原本所在位置為 [x,y],4個方向向量依序為: [0, 1], [1, 0], [0, -1], [-1, 0],當移動到下一格位置[new_x,new_y],相當於原本位置加上方向向量,即 [new_x,new_y]=[x,y]+[d_x,d_y],因此我們僅需留意碰到邊界時改變方向並更新邊界即可。

參考程式碼

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

        # set initial values
        total_count = len(matrix) * len(matrix[0])
        count = 0

        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        d = 0
        boundary = [[0, len(matrix[0]) - 1], [len(matrix) - 1, len(matrix[0]) - 1], [len(matrix) - 1, 0], [1, 0]]
        boundary_renew = [[1, -1], [-1, -1], [-1, 1], [1, 1]]
        ans = []

        i = 0
        j = 0

        while count < total_count:
            # print(i, j, boundary, ans)
            element = matrix[i][j]
            ans.append(element)
            count += 1

            # check whether touched boundaries
            if [i, j] == boundary[d]:
                # print("touched")
                # update the directions and boundaries
                boundary[d][0] += boundary_renew[d][0]
                boundary[d][1] += boundary_renew[d][1]
                d = (d + 1) % 4

            i, j = i + directions[d][0], j + directions[d][1]

        return ans

小結

此為N=2的情形,當改為其他維度時仍成立,且當移動方式改變時,我們僅需修改方向向量及步長。
運用此方法亦可解另外兩道延伸題 Spiral Matrix II ([2]),Spiral Matrix III ([3])。
我將各題解法實作,並上傳程式碼 ([4])到此。

參考資料

[1] leetcode: Spiral Matrix
[2] leetcode: Spiral Matrix II
[3] leetcode: Spiral Matrix III
[4] hero0963: 程式碼實作


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言