力扣-数组-螺旋矩阵-循环不变量

 解法:

这道题并没有用到有多高深的算法,但是需要保证好循环不变量原则,即每次循环的区间能改变,如果每次循环区间都改变,那么我们就需要做无数个判断,这显然是不符合题意的。

博主采取了“左闭右开”的区间取法。我们将数据按照螺旋存入二维数组,需要转多少圈呢?

每存储一圈时,在下一圈开始存储时,我们可以看到任意一条边上都消失了两个顶点,因此共需要存储n/2圈。

每一次存储时的开始位置是一个变化的量,第一次从第0列开始,第二次从1列开始......由此我们可以见得在存储一圈后需要给start(开始位置)++

同样因为采取了左闭右开的区间取法,结束的位置同样是动态的。

按照题中给出的循环顺序,分别写入四个循环进行条件判断最终就可以得到答案。

注意:如果所给的n是奇数的话,中间会多出一个数,这个数的位置是start结束位置++

注意:arr[i][j]=cont++

        等于arr[i][j]=cont;

                cont++;

        

class Solution {
    public int[][] generateMatrix(int n) {
       int cont=1;
       int start=0;//起始位置
       int loop=0;//终止时,停止变量
       int i,j;//i是行,j是列
       int[][] arr=new int[n][n];//创建数组将元素存入
       while(loop++<n/2){//每次转一圈,一条边都会少两个数,少了多少个两个数就是转多少圈
            //上面的边,从左到右遍历
            for(j=start;j<n-loop;j++){
                arr[start][j]=cont++;
            }
            //右边的边,从上到下遍历
            for(i=start;i<n-loop;i++){
                arr[i][j]=cont++;
            }
            //下边的边,从右到左遍历
            for(;j>=loop;j--){
                arr[i][j]=cont++;
            }
            for(;i>=loop;i--){
                arr[i][j]=cont++;
            }
            start++;
       }

       if(n%2==1){
           arr[start][start]=cont;//如果是奇数,中间最后的元素是遍历结束的start
       }
       return arr;
    }
}

解法:和上道题类似,这种题是真的很恶心,虽然没什么套路就记着循环不变量,但是只要一变化就要处理一些细节问题。

还是和上面那道题一样采取左闭右开的区间取法,遍历完成后我们发现,循环的圈数是较短边2的倍数,同时如果较短边是奇数,则会剩下一条线,这个线需要我们手动去加入,起始位置是循环结束的start,终止位置是长边长度剪去start。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
         ArrayList<Integer> list = new ArrayList<>();
        int n = matrix.length;//有n列
        int m = matrix[0].length;//有m行
        int start = 0;
        int end = 1;
        int loop = 0;
        int i = 0, j = 0;//i 行 j列
        while (loop < n / 2 && loop < m / 2) {
            //上边
            for (j = start; j < m - end; j++) {
                list.add(matrix[start][j]);
            }

            //右边
            for (i = start; i < n - end; i++) {
                list.add(matrix[i][j]);
            }

            //下面
            for (; j >= end; j--) {
                list.add(matrix[i][j]);
            }

            //左边
            for (; i >= end; i--) {
                list.add(matrix[i][j]);
            }
            start++;
            end++;
            loop++;
        }

        //找到行和列之间较小的那个数,如果循环了几圈,最后这条边还剩下一个元素,那么必然会剩下一根线。
        //找到中间数,掐头去尾输入进去就可以了
         if (n < m &&n%2==1) {
            //n比较小
            int s = (n + 1) / 2 - 1;
            for (int k = start; k < m - start; k++) {
                list.add(matrix[s][k]);
            }
        } else if(m <= n &&m%2==1){
            int s = (m + 1) / 2 - 1;
            for (int k = start; k < n - start; k++) {
                list.add(matrix[k][s]);
            }
        }
        return list;
    }
}

解法:

和上题一摸一样,只是加入了将这些数据打印出来,那么我们只需要装一个一维数组把集合中的每个元素都倒入就行了,但是要注意力扣会用特殊情况卡我们,即啥元素都没有,因此我们在开始的时候要做一个条件判断。

class Solution {
    public int[] spiralOrder(int[][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        int[] arr=new int[0];
        if(matrix == null || matrix.length == 0)
        return arr;
        int n = matrix.length;//有n行
        int m = matrix[0].length;//有m列
        int start = 0;
        int end = 1;
        int loop = 0;
        int i = 0, j = 0;//i 行 j列
        while (loop < n / 2 && loop < m / 2) {
            //上边
            for (j = start; j < m - end; j++) {
                list.add(matrix[start][j]);
            }

            //右边
            for (i = start; i < n - end; i++) {
                list.add(matrix[i][j]);
            }

            //下面
            for (; j >= end; j--) {
                list.add(matrix[i][j]);
            }

            //左边
            for (; i >= end; i--) {
                list.add(matrix[i][j]);
            }
            start++;
            end++;
            loop++;
        }

        //找到行和列之间较小的那个数,如果循环了几圈,最后这条边还剩下一个元素,那么必然会剩下一根线。
        //找到中间数,掐头去尾输入进去就可以了
        if (n < m &&n%2==1) {
            //n比较小
            int s = (n + 1) / 2 - 1;
            for (int k = start; k < m - start; k++) {
                list.add(matrix[s][k]);
            }
        } else if(m <= n &&m%2==1){
            int s = (m + 1) / 2 - 1;
            for (int k = start; k < n - start; k++) {
                list.add(matrix[k][s]);
            }
        }
        int[] arr1=new int[n*m];
        for(int p=0;p<n*m;p++){
            arr1[p]=list.get(p);
        }
        return arr1;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值