刷题笔记(四)--数组类型:模拟

系列文章目录

刷题笔记(一)–数组类型:二分法
刷题笔记(二)–数组类型:双指针法
刷题笔记(三)–数组类型:滑动窗口

题录

54. 螺旋矩阵

54. 螺旋矩阵

先看题目截图:
在这里插入图片描述

注意,这道题和下道题的处理思路都是一样的,所以我这里把做法移动到了总结部分

public static List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> list = new ArrayList<>();
        if(matrix == null || matrix.length == 0){
            return list;
        }

        int left = 0;//定义左边界
        int right = matrix[0].length - 1;//定义右边界

        int top = 0;//定义上边界
        int bottom = matrix.length - 1;//定义下边界

        int count = matrix.length * matrix[0].length;//记录数组种类

        //这里我的遍历思想是左闭右闭
        while(count >= 1){
            //先从左上到右上
            for (int i = left; i <= right && count >= 1; i++) {
                list.add(matrix[top][i]);
                count--;
            }
            top++;

            //再从右上到右下
            for (int i = top; i <= bottom && count >= 1; i++) {
                list.add(matrix[i][right]);
                count--;
            }
            right--;

            //再从右下到左下
            for(int i = right;i >= left && count >= 1;i--){
                list.add(matrix[bottom][i]);
                count--;
            }
            bottom--;

            //再从左下到左上
            for (int i = bottom; i >= top && count >= 1; i--) {
                list.add(matrix[i][left]);
                count--;
            }
            left++;
        }
        return list;
    }

59. 螺旋矩阵 II

59. 螺旋矩阵 II

还是老规矩,先看题
在这里插入图片描述

这道题的做法和上道题做法我都放在总结篇里面讲解。

public int[][] generateMatrix(int n) {
        int[][] arr = new int[n][n];

        int left = 0;//定义左边界
        int right = n - 1;//定义右边界

        int top = 0;//定义上边界
        int bottom = n - 1;//定义下边界

        int count = 1;//定义当前加入的数字
        while(count <= n * n){
            //首先从左上往右上遍历
            for (int i = left; i <= right && count <= n*n; i++) {
                arr[top][i] = count;
                count++;
            }
            top++;

            //然后是从右上往右下遍历
            for (int i = top; i <= bottom && count <= n * n; i++) {
                arr[i][right] = count;
                count++;
            }
            right--;

            //然后是从右下往左下遍历
            for (int i = right; i >= left && count <= n * n; i--) {
                arr[bottom][i] = count;
                count++;
            }
            bottom--;

            //然后是从左下往左上遍历
            for (int i = bottom; i >= top && count <= n * n; i--) {
                arr[i][left] = count;
                count++;
            }
            left++;
        }
        return arr;
    }

总结

可以看到,我这篇博客的命题叫做“模拟”,什么意思呢?也就是模拟输出。这种类型的题不会涉及什么算法,但是这个写代码题的过程却十分考验程序员对代码的细节处理。
那么我们要怎样螺旋遍历上述的数组呢?当然,肯定不能上去直接三七二十一就各种判断一顿操作,这样很快就把自己弄混了。做这种题一定要有条理性,也就是坚持循环不变量原则。什么意思呢?
这样解释:如果我们要顺时针螺旋遍历一个数组,怎么遍历?无非就是

上行从左到右
右列从上到下
下行从右到左
左列从下到上

这样我们就算是走完一圈了。可是问题就是在这里,我们边界很不明确呀,什么意思呢?我们看下面这个遍历
在这里插入图片描述
边界是不是很不明确,如果你还觉得明显,那再来
在这里插入图片描述

这样是不是闲的很乱?就很没有条理性,边界值就很不明确,哪里起步,哪里停止,临界限定条件是啥,一点都不清楚。那么一个条理清晰的遍历是怎样遍历的呢?
在这里插入图片描述

这个和上面两种遍历方式的差别是啥?可以发现下面这种的就很清晰。为什么清晰?
因为它的遍历条件很明确:每条边左闭右开。当前遍历取不到拐角处的方块,它会把每个拐角处的那个方块统一交给下次循环处理。
坚持每条边的遍历原则,我们就可以清晰完整的遍历整个数组。可是这个时候细心的读者就会发现了,我这里说的是左闭右开,但是我做题可不是这样搞得呀!我做题用的另外一种更为清晰的限制条件:每条边左闭右闭。什么意思呢?就是我每次遍历都会遍历完当前的行或者列,啥意思呢?看下图:
在这里插入图片描述
注意看我上面的方块的脱离顺序,每次都是当前一行或者当前一列的全部脱离,然后一点点缩小范围。这种的写法有什么好处呢?就是我们只需要控制边界值就好了,不要额外定义变量来进行遍历。更有利于我们去控制变量和理解代码思想。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值