LeetCode 54. 螺旋矩阵

54. 螺旋矩阵

题目:给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
链接 https://leetcode.cn/problems/spiral-matrix/

个人思路
  1. 根据前面做过的题LeetCode 59. 螺旋矩阵 II代码进行改动,这里不一样的就是这个并不是一个方阵,直接使用之前的代码是不可行的,因为当m=1或者n=1时候会出现重复,走回已经走过的路,刚开始是将这两种单独列出来讨论:
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        ans = []
        m = len(matrix)-1
        n = len(matrix[0])-1
        if m == 0:
            return matrix[0]
        if n == 0:
            for i in matrix:
                ans.append(i[0])
            return ans
        l,r,t,b = 0,n,0,m
        num = 1
        while num <= (m+1) * (n+1):
            # 左到右
            for i in range(l,r+1):
                ans.append(matrix[l][i])
                num += 1
            t += 1
            # 上到下
            for i in range(t,b+1):
                ans.append(matrix[i][r])
                num += 1
            r -= 1
            # 右到左
            for i in range(r,l-1,-1):
                ans.append(matrix[b][i])
                num += 1
            b -= 1
            # 下到上      
            for i in range(b,t-1,-1):
                ans.append(matrix[i][l])
                num += 1
            l += 1
        return ans

在用例[[1,2,3,4],[5,6,7,8],[9,10,11,12]]返回[1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7, 6]说明这里还是会往回走一步,所以下面进行改进:要想右到左,必须bottom大于等于top;同理,要想下到上, 必须right大于等于left

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        ans = []
        m = len(matrix)-1
        n = len(matrix[0])-1
        # if m == 0:
        #     return matrix[0]
        # if n == 0:
        #     for i in matrix:
        #         ans.append(i[0])
        #     return ans
        l,r,t,b = 0,n,0,m
        num = 1
        while num <= (m+1) * (n+1):
            # 左到右
            for i in range(l,r+1):
                ans.append(matrix[l][i])
                num += 1
            t += 1
            # 上到下
            for i in range(t,b+1):
                ans.append(matrix[i][r])
                num += 1
            r -= 1
            # 右到左,必须bottom大于等于top所在下标
            if b >= t:
                for i in range(r,l-1,-1):
                    ans.append(matrix[b][i])
                    num += 1
                b -= 1
            # 下到上  
            if r >= l:  
                for i in range(b,t-1,-1):
                    ans.append(matrix[i][l])
                    num += 1
                l += 1
        return ans
复杂度分析

复杂度分析

时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。

空间复杂度:O(mn)。需要创建一个大小为 m×n 的矩阵 visited 记录每个位置是否被访问过。

其他思路
  1. 官解模拟写法
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        rows, columns = len(matrix), len(matrix[0])
        visited = [[False] * columns for _ in range(rows)]
        total = rows * columns
        order = [0] * total

        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        row, column = 0, 0
        directionIndex = 0
        for i in range(total):
            order[i] = matrix[row][column]
            visited[row][column] = True
            nextRow, nextColumn = row + directions[directionIndex][0], column + directions[directionIndex][1]
            if not (0 <= nextRow < rows and 0 <= nextColumn < columns and not visited[nextRow][nextColumn]):
                directionIndex = (directionIndex + 1) % 4
            row += directions[directionIndex][0]
            column += directions[directionIndex][1]
        return order
  1. 按层模拟
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        rows, columns = len(matrix), len(matrix[0])
        order = list()
        left, right, top, bottom = 0, columns - 1, 0, rows - 1
        while left <= right and top <= bottom:
            for column in range(left, right + 1):
                order.append(matrix[top][column])
            for row in range(top + 1, bottom + 1):
                order.append(matrix[row][right])
            if left < right and top < bottom:
                for column in range(right - 1, left, -1):
                    order.append(matrix[bottom][column])
                for row in range(bottom, top, -1):
                    order.append(matrix[row][left])
            left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
        return order
  1. 评论区
    用计数判断是否遍历完挺好,只要计数没有到0,肯定是不会越界的
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        r = len(matrix)
        c = len(matrix[0])
        # print(f"r = {r}, c = {c}")
        if r == 1 or c == 1:
            return [item for sublist in matrix for item in sublist]        
        res = []
        l = 0
        t = 0
        right = c - 1
        b = r - 1
        tmp = len(matrix) * len(matrix[0])
        while tmp >= 1:
            # print(f"tmp = {tmp}, res = {res}, l = {l}, t = {t}, right = {right}, b = {b}")
            # right: fix row
            for i in range(l, right + 1):
                if tmp >= 1:
                    res.append(matrix[t][i])
                    tmp -= 1
            t += 1
            # down: fix column
            for i in range(t, b + 1):
                if tmp >= 1:
                    res.append(matrix[i][right])
                    tmp -= 1
            right -= 1                  
            # left: fix row
            for i in range(right, l - 1, -1):
                if tmp >= 1:
                    res.append(matrix[b][i])
                    tmp -= 1
            b -= 1
            # up: fix column
            for i in range(b, t - 1, -1):
                if tmp >= 1:
                    res.append(matrix[i][l])
                    tmp -= 1
            l += 1
        return res

参考:
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/spiral-matrix/solution/luo-xuan-ju-zhen-by-leetcode-solution/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值