96.螺旋矩阵

一、题目描述

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、解题思路

方案一:直接模拟

  • 往右开始遍历,特点就是row不变,col加1,一直到超出索引范围或遇到已经遍历的元素。
  • 往下遍历,特点是row加1,col不变,一直到超出索引范围或遇到已经遍历的元素。
  • 往左遍历,特点是row不变,col减1,一直到超出索引范围或遇到已经遍历的元素。
  • 往上遍历,特点是row减1,col不变,一直到超出索引范围或遇到已经遍历的元素。
    在这里插入图片描述

使用一个2*4的数组来存储方向和行列的变化,2表示行和列的变化,4指四个方向。

方案二:按层模拟

使用四个指针:startRowendRowstartColendCol,指针初始位置如下,开始遍历:

第一步:第一层的遍历

  • 先从startRow行开始遍历,从右往左,遍历到从startColendCol结束;
  • 然后遍历最后一列,从startRow+1行一直到endRow结束
  • 再遍历最后一行,从endCol-1,一直到startCol+1结束
  • 最后再遍历第一列,从endRowstartRow+1
    在这里插入图片描述
    第二步:内层遍历

先将startRow++endRow--startCol++endCol--,然后再按照第一步的遍历方式继续遍历即可
在这里插入图片描述

三、代码演示

方案一:

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
         //使用2*4的数组:往右,往下,往左,往上,0表示不变,1是加1,-1是减1
        int[][] dirs = {{0,1},{1,0},{0,-1},{-1,0}};

        //先得到矩阵的行列长度
        int m = matrix.length;;
        int n = matrix[0].length;

        int row = 0, col = 0;
        //使用一个变量来控制方向,默认往右走
        int di = 0;
        //存放结果
        List<Integer> res = new ArrayList<>();
        //使用一个boolean来判断某个元素是否被访问
        boolean[][] seen = new boolean[m][n];

        for (int i=0; i<m*n; i++){
            res.add(matrix[row][col]);
            seen[row][col] = true;  //表示某个元素被访问

            //dirs是一个2行4列的数组,dirs[di][0]表示取出dirs中第di行的第1个元素
            int nextRow = row + dirs[di][0];  //表示行的变化
            int nextCol = col + dirs[di][1];  //表示列的变化

            if (nextRow<0 || nextRow>=m || nextCol<0 || nextCol>=n || seen[nextRow][nextCol]){
                //改变方向,四个方向,di表示0,1,2,3,dirs的四行
                di = (di+1)%4;
            }

            //更新初始行列
            row = row + dirs[di][0];
            col = col + dirs[di][1];
        }
        return res;
    }
}

方案二:

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
         List<Integer> res = new ArrayList<>();

        //先定义四个指针
        int startRow = 0, endRow = matrix.length - 1;
        int startCol = 0, endCol = matrix[0].length - 1;

        while (startRow <= endRow && startCol <= endCol) {
            // top 行
            for (int col = startCol; col <= endCol; col++){
                res.add(matrix[startRow][col]);
            }
            // right 列
            for (int row = startRow + 1; row <= endRow; row++){
                res.add(matrix[row][endCol]);
            }

            //判断边界
            if (startRow < endRow && startCol < endCol) {
                // bottom 行
                for (int col = endCol - 1; col > startCol; col--){
                    res.add(matrix[endRow][col]);
                }
                // left 列
                for (int row = endRow; row > startRow; row--){
                    res.add(matrix[row][startCol]);
                }
            }
            startRow++;
            endRow--;
            startCol++;
            endCol--;
        }
        return res;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值