当前位置: 首页 > news >正文

【二刷代码随想录】螺旋矩阵求解方法、推荐习题

一、求解方法 

(1)按点模拟路径

        在原有坐标的基准上,叠加 横纵坐标 的变化值,求出下一位置,并按题完成要求。但需注意转角的时机判断,特别是最后即将返回上一出发点的位置。

(2)按层模拟路径

        在原有的形状基础上,画出 上下左右 四根边界线,按照顺序完成画圈。但需要关注单行或单列可能存在重复的情况,因此需在操作 边界线时加上判定条件。

(3)心路历程

        最开始掌握的是 Carl 教的循环画框类的思路,但是它的应用是在方形样式,其中的 offset 和 中间元素处理对于方形图案比较好处理,但是针对矩形样式,我真的不知道要怎么改了。后改学其他思路,也就是上述两种。

二、推荐例题

(1)方形样式的螺旋矩阵

        59. 螺旋矩阵 II

方法1:点模拟

class Solution {
    public int[][] generateMatrix(int n) {    
        int curNum = 1;
        int maxNum = n * n;

        int curRow = 0;
        int curCol = 0;

        int dirIndex = 0;
        int[][] dirs = {{0,1}, {1,0}, {0,-1}, {-1,0}};

        int[][] res = new int[n][n];

        while(curNum <= maxNum){
            res[curRow][curCol] = curNum++;

            //判定后续位置是否越界
            int nextRow = curRow + dirs[dirIndex][0];
            int nextCol = curCol + dirs[dirIndex][1];
            //需要加一个res[nextRow][nextCol] != 0 因为走了一圈之后就回到了原点,需要避免回原点,而是调整方向
            //比如三阶矩阵中的最后9,若不调整方向,则会放到原点处
            if(nextRow < 0 || nextRow > n-1 || nextCol < 0 || nextCol > n-1 || res[nextRow][nextCol] != 0){
                dirIndex = (dirIndex+1) % 4;
            }

            curRow = curRow + dirs[dirIndex][0];
            curCol = curCol + dirs[dirIndex][1];
        }

        return res;
    }
}

方法2:层模拟

class Solution {
    public int[][] generateMatrix(int n) {    
        int left = 0;
        int right = n-1;
        int top = 0;
        int bottom = n-1;
        int num = 1;

        int[][] res = new int[n][n];

        while(left <= right && top <= bottom){
            //上:从左往右-----j 从 left ---> right
            for(int j = left; j <= right; j++){
                res[top][j] = num++;
            }
            top++;

            //右:从上到下-----i 从 top ---> bottom
            for(int i = top; i <= bottom; i++){
                res[i][right] = num++;
            }
            right--;

            if(top <= bottom){
                //下:从右到左-----j 从 right ---> left
                for(int j = right; j >= left; j--){
                    res[bottom][j] = num++;
                }
                bottom--;
            }
            

            if(left <= right){
                //左:从下到上-----i 从 bottom ---> top
                for(int i = bottom; i >= top; i--){
                    res[i][left] = num++;
                }
                left++;
            }
        }

        return res;
    }
}

方法3:“循环画框”

class Solution {
    public int[][] generateMatrix(int n) {    
        int loopCur = 1;        //当前所处的圈数
        int loopCnt = n / 2;    //所需绘制的完整圈数
        int xStart = 0;         //横坐标的开始坐标
        int yStart = 0;         //纵坐标的开始坐标
        int offset = 1;         //当前绘制圈的偏置值
        int num =  1;           //当前绘制的数字
        int i,j;                //绘制地图用的横纵坐标
        int[][] res = new int[n][n];

        while(loopCur <= loopCnt){
            //上:从左往右-----j 从 yStart ---> n-offset
            for(j = yStart; j < n-offset; j++){
                res[xStart][j] = num++;
            }

            //右:从上到下-----i 从 xStart ---> n-offset
            for(i = xStart; i < n-offset; i++){
                res[i][j] = num++;
            }

            //下:从右到左-----j 递减到 yStart+1
            for(; j > yStart; j--){
                res[i][j] = num++;
            }

            //左:从下到上-----i 递减到 xStart+1
            for(; i > xStart; i--){
                res[i][j] = num++;
            }

            offset++;   //调整偏置值
            loopCur++;
            xStart++;
            yStart++;
        }

        if(1 == n%2){
            res[xStart][yStart] = num;
        }
        
        return res;
    }
}

 (2)矩形样式的螺旋矩阵

        54.螺旋矩阵

方法1:点模拟

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

        if(matrix == null){
            return res;
        }

        int rows = matrix.length;
        int cols = matrix[0].length;
        int cnt = rows * cols;

        if (rows == 0 || cols == 0) {
            return res;
        }

        int curRow = 0;
        int curCol = 0;

        int dirIndex = 0;
        int[][] dirs = {{0,1}, {1,0}, {0,-1}, {-1,0}};

        boolean[][] visited = new boolean[rows][cols];


        while(cnt > 0){
            res.add(matrix[curRow][curCol]);
            visited[curRow][curCol] = true;

            //判定后续位置是否越界
            int nextRow = curRow + dirs[dirIndex][0];
            int nextCol = curCol + dirs[dirIndex][1];
            //需要加一个res[nextRow][nextCol] != 0 因为走了一圈之后就回到了原点,需要避免回原点,而是调整方向
            //比如三阶矩阵中的最后9,若不调整方向,则会放到原点处
            if(nextRow < 0 || nextRow > rows-1 || nextCol < 0 || nextCol > cols-1 || visited[nextRow][nextCol] != false){
                dirIndex = (dirIndex+1) % 4;
            }

            curRow = curRow + dirs[dirIndex][0];
            curCol = curCol + dirs[dirIndex][1];

            cnt--;
        }

        return res;
    }
}

方法2:层模拟

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

        if(matrix == null){
            return res;
        }

        int rows = matrix.length;
        int cols = matrix[0].length;

        if (rows == 0 || cols == 0) {
            return res;
        }

        int top = 0;
        int bottom = rows -1;
        int left = 0;
        int right = cols -1;

        while(top <= bottom && left <= right){
            //上:从左到右
            for(int j = left; j <= right; j++){
                res.add(matrix[top][j]);
            }
            top++;

            //右:从上到下
            for(int i = top; i <= bottom; i++){
                res.add(matrix[i][right]);
            }
            right--;

            //下:从右到左
            if(top <= bottom){  //若不判断,遇见单行,则会重复处理
                for(int j = right; j >= left;j--){
                res.add(matrix[bottom][j]);
                }
            }
            
            bottom--;

            //左:从下到上
            if(left <= right){  //若不判断,遇见单列,则会重复处理
                for(int i = bottom; i >= top; i--){
                res.add(matrix[i][left]);
                }
            }
            
            left++;
        }

        return res;
    }
}

方法3: “循环画框”--错误代码演示,没改出来

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

        int rows = matrix.length;
        int cols = matrix[0].length;
        int loopCur = 1;
        int loopCnt = rows/2 + 1;    //为便捷处理中心区域的多个数据
        int xStart = 0;
        int yStart = 0;
        int offset = 1;

        //因为增加了圈数,导致单行的矩阵会重复打印
        if(rows == 1){
            for(int temp = 0; temp < cols; temp++){
                res.add(Integer.valueOf(matrix[0][temp]));
            }

            return res;
        }

        //因为增加了圈数,导致单列的矩阵会重复打印
        if(cols == 1){
            for(int temp = 0; temp < rows; temp++){
                res.add(Integer.valueOf(matrix[temp][0]));
            }

            return res;
        }

        int i,j;
        while(loopCur <= loopCnt){
            //上:从左到右
            for(j = yStart; j < cols-offset; j++){
                res.add(matrix[xStart][j]); 
            }
            //右:从上到下
            for(i = xStart; i < rows-offset; i++){
                res.add(matrix[i][j]);
            }
            //下:从右到左
            for(; j > yStart; j--){
                res.add(matrix[i][j]);
            }
            //左:从下到上
            for(; i > xStart; i--){
                res.add(matrix[i][j]);
            }
            offset++;
            loopCur++;
            xStart++;
            yStart++;
        }
        if(rows == cols && rows%2 ==1){
            res.add(matrix[xStart-1][yStart-1]);
        }
        return res;
    }
}
http://www.dtcms.com/a/99512.html

相关文章:

  • 表格图表切换,图表无法展示问题复盘
  • 工作记录 2017-03-13
  • Python CSV 数据分析:问题排查与解决全记录
  • Windows学习笔记(3)关于事件日志
  • linux的文件
  • Visual Basic语言的折线图
  • Ubuntu 系统中,每日健康检查
  • vulnhub-Node1
  • C#:第一性原理拆解字段(fields)
  • ElasticSearch 分词器
  • kill子进程后再wait可以吗?
  • java性能优化实例
  • 如何估算和优化 Gas
  • 学习通-操作系统第五版费翔林-习题-标答
  • 【AI学习】深度学习,人工神经网络
  • 破解美业数字化迷思:中小门店的智慧转型之路
  • 代码随想录day31 贪心part05
  • 蓝桥杯真题------R格式(高精度乘法,高精度加法)
  • Flutter 开发环境配置--宇宙级教学!
  • 【通道注意力机制】【SENet】Squeeze-and-Excitation Networks
  • 高并发系统下的订单号生成服务设计与实现
  • Node.js Express 安装并使用 nodemon
  • 多路径 TCP 调度的另一面
  • Vue3 事件处理
  • 英伟达GB300新宠:新型LPDDR5X SOCAMM内存
  • 【12】Ajax的原理和解析
  • C语言之链表增删查改
  • 【Java SE】Java比较器:Comparable、Comparator
  • Python的ASGI Web 服务器之uvicorn
  • 图解AUTOSAR_SWS_SynchronizedTimeBaseManager