数组-螺旋矩阵ⅠⅡⅢ-中等-20210907

54螺旋矩阵

1. 题目描述

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例

[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

[[1, 2, 3, 4],
 [5, 6, 7, 8],
 [9, 10, 11, 12]]
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

提示

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j]<= 100

2. 题目解答

2.1 按层模拟

思路:可以将矩阵看成若干层,首先输出最外层的元素,其次输出次外层的元素,直到输出最内层的元素。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PROoGdvS-1631255569369)(F:\0. Note\Typora-image\latex\54_fig1.png)]

  • 从左到右遍历上侧元素,依次为$ (\textit{top}, \textit{left}) 到 到 (\textit{top}, \textit{right})$
  • 从上到下遍历右侧元素,依次为 ( top + 1 , right ) (\textit{top} + 1, \textit{right}) (top+1,right) ( bottom , right ) (\textit{bottom}, \textit{right}) (bottom,right)
  • 如果 left < right \textit{left} < \textit{right} left<right且$ \textit{top} < \textit{bottom}$:
    • 则从右到左遍历下侧元素,依次为$ (\textit{bottom}, \textit{right} - 1) $到 ( bottom , left + 1 ) (\textit{bottom}, \textit{left} + 1) (bottom,left+1)
    • 从下到上遍历左侧元素,依次为$ (\textit{bottom}, \textit{left}) 到 到 (\textit{top} + 1, \textit{left})$
  • 遍历完当前层的元素之后,将$ \textit{left} 和 和 \textit{top} 分 别 增 加 1 , 将 分别增加 1,将 1 \textit{right} $和 bottom \textit{bottom} bottom分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。

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

空间复杂度: O ( 1 ) O(1) O(1),除了输出数组以外,空间复杂度是常数

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return list()
        
        row, col = len(matrix), len(matrix[0])
        left, right, top, bottom = 0, col - 1, 0, row - 1
        res = []
        while left <= right and top <= bottom:  # =成立时是最里面的一层
            for c in range(left, right + 1):
                res.append(matrix[top][c])
            for r in range(top + 1, bottom + 1):
                res.append(matrix[r][right])
            if left < right and top < bottom:  # 避免只有一行t=b或一列的情况l=r,其余情况两者不相等
                for c in range(right - 1, left, -1):
                    res.append(matrix[bottom][c])
                for r in range(bottom, top, -1):
                    res.append(matrix[r][left])
            left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1
        return res

2.2 模拟

遍历题目思考清楚以下问题:

  1. 起始位置
  2. 移动方向
  3. 边界
  4. 结束条件

算法思路:

  • top, bottom, left, right 分别表示四个方向的边界。
  • x, y 表示当前位置。
  • direction 分别表示移动方向是 右、下、左、上 。
  • index表示当前的移动方向的下标,direction[index] 就是下一个方向需要怎么修改 x, y。
  • index == 0 and y == right 表示当前的移动方向是向右,并且到达了右边界,此时将移动方向更改为向下,并且上边界 top 向下移动一格。
  • 结束条件是结果数组 res 的元素个数能与 matrix 中的元素个数。

时间复杂度: O ( m n ) O(mn) O(mn)
空间复杂度: O ( 1 ) O(1) O(1),除了输出数组以外,空间复杂度是常数

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix or not matrix[0]:
            return []
        row, col = len(matrix), len(matrix[0])
        left, right, top, bottom = 0, col - 1, 0, row - 1  # 边界
        x, y = 0, 0  # 起始位置
        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]  # 移动方向[(0, 1), (1, 0), (0, -1), (-1, 0)]  
        index = 0  # directions下标
        
        res = []
        while len(res) != row * col:  # 结束条件
            res.append(matrix[x][y])
            if index == 0 and y == right:
                index += 1
                top += 1
            elif index == 1 and x == bottom:
                index += 1
                right -= 1
            elif index == 2 and y == left:  # bug y写成了x
                index += 1
                bottom -= 1
            elif index == 3 and x == top:  # 已经被赋值了新top值
                index += 1
                left += 1
            index %= 4
            x += directions[index][0]
            y += directions[index][1]
        return res

3. 错解


59螺旋矩阵Ⅱ

1. 题目描述

给你一个正整数 n ,生成一个包含 1n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix

示例

[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]
 
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

[[1]]
输入:n = 1
输出:[[1]]

提示

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

2. 题目解答

2.1 尝试-按层模拟

思路:

  • 生成所有的元素一维数组res,将每个值依次放入matrix的对应位置
  • matrix的位置一层一层指定索引

时间复杂度: O ( n 2 ) O(n^2) O(n2) 其中 n 是给定的正整数。矩阵的大小是 n × n n \times n n×n,需要填入矩阵中的每个元素。

空间复杂度: O ( 1 ) O(1) O(1),除了返回的矩阵以外,空间复杂度是常数

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        res = [i for i in range(1, n*n + 1)]
        matrix = [[0]*n for i in range(n)]  # 生成一个空矩阵,将res里的元素逐个放入
        left, right, top, bottom  = 0, n - 1, 0, n - 1  # 边界
        i = 0
        while left <= right and top <= bottom:
            for c in range(left, right + 1):
                matrix[top][c] = res[i]
                i += 1
            for r in range(top + 1, bottom + 1):
                matrix[r][right] = res[i]
                i += 1
            for c in range(right - 1, left, -1):
                matrix[bottom][c] = res[i]
                i += 1
            for r in range(bottom, top, -1):
                matrix[r][left] = res[i]
                i += 1
            left, right, top, bottom =  left + 1, right - 1, top + 1, bottom - 1
        return matrix

改进:去除res数组

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix = [[0]*n for i in range(n)]  # 生成一个空矩阵,将res里的元素逐个放入
        left, right, top, bottom  = 0, n - 1, 0, n - 1  # 边界
        i = 0
        res = 1
        while left <= right and top <= bottom:
            for c in range(left, right + 1):  # 统一左闭右开要除了第一行,考虑最里面取一个值情况
                matrix[top][c] = res
                res += 1
            for r in range(top + 1, bottom):
                matrix[r][right] = res
                res += 1
            for c in range(right, left, -1):
                matrix[bottom][c] = res
                res += 1
            for r in range(bottom, top, -1):
                matrix[r][left] = res
                res += 1
            left, right, top, bottom =  left + 1, right - 1, top + 1, bottom - 1
        return matrix
        

改进:去除res数组/统一左闭右开,n为奇数要额外填充一次中心

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        matrix = [[0]*n for i in range(n)]  # 生成一个空矩阵,将res里的元素逐个放入
        left, right, top, bottom  = 0, n - 1, 0, n - 1  # 边界
        i = 0
        res = 1
        while left <= right and top <= bottom:
            for c in range(left, right):  # 统一左闭右开
                matrix[top][c] = res
                res += 1
            for r in range(top, bottom):
                matrix[r][right] = res
                res += 1
            for c in range(right, left, -1):
                matrix[bottom][c] = res
                res += 1
            for r in range(bottom, top, -1):
                matrix[r][left] = res
                res += 1
            left, right, top, bottom =  left + 1, right - 1, top + 1, bottom - 1
        
        # 如果阶数为奇数,额外填充一次中心
        if n % 2:
            matrix[n // 2][n // 2] = res
        return matrix

2.2 模拟

遍历题目思考清楚以下问题:

  1. 起始位置
  2. 移动方向
  3. 边界
  4. 结束条件

时间复杂度: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( 1 ) O(1) O(1),除了输出数组以外,空间复杂度是常数

class Solution:    def generateMatrix(self, n: int) -> List[List[int]]:        left, right, top, bottom = 0, n - 1, 0, n - 1  # 边界        x, y = 0, 0  # 起始位置        directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]  # 移动方向[(0, 1), (1, 0), (0, -1), (-1, 0)]          index = 0  # directions下标        res = 1        matrix  = [[0]*n for i in range(n)]        while res <= n*n:  # 结束条件            matrix[x][y] = res            res += 1            if index == 0 and y == right:                index += 1                top += 1            elif index == 1 and x == bottom:                index += 1                right -= 1            elif index == 2 and y == left:  # bug y写成了x                index += 1                bottom -= 1            elif index == 3 and x == top:  # 已经被赋值了新top值                index += 1                left += 1            index %= 4            x += directions[index][0]            y += directions[index][1]        return matrix

3. 错解


885螺旋矩阵Ⅲ

1. 题目描述

R R R C C C 列的矩阵上,我们从 ( r 0 , c 0 ) (r_0, c_0) (r0,c0) 面朝东面开始。这里,网格的西北角位于第一行第一列,网格的东南角位于最后一行最后一列。
现在,我们以顺时针按螺旋状行走,访问此网格中的每个位置。每当我们移动到网格的边界之外时,我们会继续在网格之外行走(但稍后可能会返回到网格边界)。
最终,我们到过网格的所有 R * C 个空间。
按照访问顺序返回表示网格位置的坐标列表。

示例1

输入:R = 1, C = 4, r0 = 0, c0 = 0输出:[[0,0],[0,1],[0,2],[0,3]]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p9y8QrNp-1631255569370)(F:\0. Note\Typora-image\latex\example_1.png)]

示例2

输入:R = 5, C = 6, r0 = 1, c0 = 4输出:[[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4],[3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1],[0,1],[4,0],[3,0],[2,0],[1,0],[0,0]]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ifpXQxp3-1631255569371)(F:\0. Note\Typora-image\latex\example_2.png)]

提示

  • 1 <= R <= 100
  • 1 <= C <= 100
  • 0 <= r_0 < R
  • 0 <= c_0 < C

2. 题目解答

2.1 模拟

思路:

1.确立四个边界Left, Right, Upper, Bottom;
2.当一个方向达到边界时,调整方向;
3.根据方向更新下一个节点
4.当节点在矩阵范围内,则加入到res中

时间复杂度: O ( m a x ( R , C ) 2 ) O(max(R,C)^2) O(max(R,C)2)

空间复杂度: O ( 1 ) O(1) O(1),结果需要 R ∗ C R*C RC

class Solution:    def spiralMatrixIII(self, rows: int, cols: int, rStart: int, cStart: int) -> List[List[int]]:        res = []        around = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 顺时针方向,每次绕一个正方形        Left, Right, Upper, Bottom = cStart - 1, cStart + 1, rStart - 1, rStart + 1  ##四个方向的边界        x, y, num, Dir = rStart, cStart, 1, 0  ##(x, y)为当前节点,num为当前查找的数字,Dir为当前的方向        while num <= rows * cols:            if x >= 0 and x < rows and y >= 0 and y < cols:  ##(x, y)在矩阵中                res.append([x, y])                num += 1            if Dir == 0 and y == Right:  ##向右到右边界                Dir += 1  ##调转方向向下                Right += 1  ##右边界右移            elif Dir == 1 and x == Bottom:  ##向下到底边界                Dir += 1                Bottom += 1  ##底边界下移            elif Dir == 2 and y == Left:  ##向左到左边界                Dir += 1                Left -= 1  ##左边界左移            elif Dir == 3 and x == Upper:  ##向上到上边界                Dir = 0                Upper -= 1  ##上边界上移            x += around[Dir][0]            y += around[Dir][1]        return res

3. 错解


  • 剑指Offer 29.顺时针打印矩阵

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值