螺旋矩阵

关于螺旋矩阵,也是面试的高频考点,但是这个题方法性强,比较简单,我一边做题,一边整理笔记,希望可以帮助到大家,图片上传太麻烦,大家直接去题目里面看

题目:54. 螺旋矩阵

难度中等
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
方法二:按层模拟
可以将矩阵看成若干层,首先输出最外层的元素,其次输出次外层的元素,直到输出最内层的元素。

定义矩阵的第 k 层是到最近边界距离为 k 的所有顶点。例如,下图矩阵最外层元素都是第 1 层,次外层元素都是第 2层,剩下的元素都是第 3 层。

[[1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 2, 2, 1],
[1, 2, 3, 3, 3, 2, 1],
[1, 2, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1]]
对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于(top,left),右下角位于 (bottom,right),按照如下顺序遍历当前层的元素。
从左到右遍历上侧元素,依次为(top,left) 到 (top,right)。

从上到下遍历右侧元素,依次为 (top+1,right) 到(bottom,right)。

如果left<right 且 top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到 (top+1,left)。

遍历完当前层的元素之后,将eft 和top 分别增加 1,将right 和 bottom 分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。

 public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> order=new ArrayList<>();
        int row=matrix.length;
        int col=matrix[0].length;
        if(matrix==null||row==0||col==0){
            return order;
        }
        int left=0;
        int right=col-1;
        int top=0;
        int bottom=row-1;
        while(left<=right&&top<=bottom){
            for(int i=left;i<=right;i++){
                order.add(matrix[top][i]);//上
            }
            for(int j=top+1;j<=bottom;j++){
                order.add(matrix[j][right]);//右
            }
            if(left<right&&top<bottom){//顶点只需要计算一次
                for(int k=right-1;k>=left;k--){
                    order.add(matrix[bottom][k]);//下
                }
                for(int m=bottom-1;m>top;m--){
                    order.add(matrix[m][left]);//左
                }
            }
            //往内缩进一层
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;

    }

复杂度分析

时间复杂度:O(mn),其中 mm 和 nn 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度:O(1)。除了输出数组以外,空间复杂度是常数

这个方法简单。

public List<Integer> spiralOrder(int[][] matrix) {
  List<Integer> order=new ArrayList<>();
        int row=matrix.length;
        int col=matrix[0].length;
        int count=row*col;//矩阵内所有的元素个数
        if(matrix==null||row==0||col==0){
            return order;
        }
        int left=0;
        int right=col-1;
        int top=0;
        int bottom=row-1;
        while(count>=1){//元素个数
            for(int i=left;i<=right&&count>=1;i++){//上第一行从左到右
                order.add(matrix[top][i]);
                
                count--;
            }
            top++;//因为第二个for循环是从上到下,top+1之后,下一个for循环的j可以从top直接开始,
            for(int j=top;j<=bottom&&count>=1;j++){//j从top直接开始,第一行的最右边的元素已经遍历过了
                order.add(matrix[j][right]);//从上到下
                
                count--;
            }
            right--;
            for(int k=right;k>=left&&count>=1;k--){//k从right直接开始(因为right已经+1),最后一列最下面的元素已经遍历过 不会重复  下面同理
                order.add(matrix[bottom][k]);//从右往左
                count--;
            }
            bottom--;
            for(int m=bottom;m>=top&&count>=1;m--){//从下往上
                order.add(matrix[m][left]);
                count--;
            }
            left++;

        }
        return order;

    }

题目:59. 螺旋矩阵 II

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

示例 1:

输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
思路:
生成一个 n×n 空矩阵 mat,随后模拟整个向内环绕的填入过程:
定义当前左右上下边界 l,r,t,b,初始值 num = 1,迭代终止值 tar = n * n;
当 num <= tar 时,始终按照 从左到右 从上到下 从右到左 从下到上 填入顺序循环,每次填入后:
执行 num += 1:得到下一个需要填入的数字;
更新边界:例如从左到右填完后,上边界 t += 1,相当于上边界向内缩 1。
使用num <= tar而不是l < r || t < b作为迭代条件,是为了解决当n为奇数时,矩阵中心数字无法在迭代过程中被填充的问题。
最终返回 mat 即可

  public int[][] generateMatrix(int n) {
        int[][] mat=new int[n][n];
        int count=n*n;//元素最大值      
        int left=0;
        int right=n-1;
        int top=0;
        int bottom=n-1;
        int a=1;
        while(a<=count){
            for(int i=left;i<=right&&a<=count;i++){//从左往右
                mat[top][i]=a++;
            }
            top++;
            for(int j=top;j<=bottom&&a<=count;j++){//从上往下
                mat[j][right]=a++;
            }
            right--;
            for(int k=right;k>=left&&a<=count;k--){//从右往左
                mat[bottom][k]=a++;
            }
            bottom--;
            for(int m=bottom;m>=top&&a<=count;m--){//从下往上
                mat[m][left]=a++;
            }
            left++;
        }
        return mat;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值