【算法系列-数组】螺旋矩阵(模拟)

【算法系列-数组】螺旋矩阵(模拟)

1. 螺旋矩阵II(LeetCode 59)

【题目链接】

1.1 思路分析🎯

这道题通过模拟解题,同时需要遵守循环不变量,明确好每一(行/列)走完时的边界值,如下:

  1. 左上到右上,不包括右上,右上交给下一轮开头;
  2. 右上到右下,不包括右下,右下交给下一轮开头;
  3. 右下到左下,不包括左下,左下交给下一轮开头;
  4. 左下到左上,不包括左上,此时一圈已结束;

在这里插入图片描述

若传进来的n为奇数,则最后中间都会剩一个空,此时将直接赋值arr [n / 2][n / 2] = count即可;

1.2 解题过程🎬

初始化 x为矩阵行首,y为矩阵列首 offset用来计算每次拐弯时的边界值,即每次循环都不取每行/每列的边界值,交给下一层循环作起始值,每一圈结束后offset需要 + 1; 圈数 q = n / 2,每次循环结束q–;

进入while循环,表示开始新一圈的赋值,之后通过四个for循环对矩阵的四条边进行赋值,直到四次循环结束,矩阵行首 x + 1,矩阵列首 y + 1, offset + 1,圈数 q - 1,重复上述过程直到q 为 0; 若 n 为 奇数,表示最后矩阵中间会单独剩下一个位,直接赋值即可

1.3 代码示例🌰

class Solution {
    public int[][] generateMatrix(int n) {
        int x = 0;
        int y = 0;
        int[][] arr = new int[n][n];
        int offset = 1;
        int count = 1;
        int i = 0, j = 0;
        int q = n / 2, mid = n / 2;
        while (q > 0) {
            j = y;
            i = x;
            for (;j < n - offset;j++) {
                arr[i][j] = count++;
            }
            for (;i < n - offset;i++) {
                arr[i][j] = count++;
            }
            for (;j > y;j--) {
                arr[i][j] = count++;
            }
            for (;i > x;i--) {
                arr[i][j] = count++;
            }
            x++;
            y++;
            offset++;
            q--;
        }
        if (n % 2 == 1) {
            arr[mid][mid] = count++;
        }
        return arr;
    }
}

2. 螺旋矩阵(LeetCode 54)

【题目链接】

2.1 思路分析🎯

这道题的解法与上道题目(螺旋矩阵II)存在一些区别,区别在于这道题:每次循环都取每行/每列最后的边界值,即做到每一轮的最后边界值在下一轮的开始都不会使用:

在这里插入图片描述

2.2 解题过程🎬

定义好初始数据:

l: 最左边界值

r: 最右边界值

t: 最上边界值

b:最下边界值

之后进入循环,在循环中依次进行理论循环移动:

从左到右:让索引 i = l,从左到右遍历直到 i > r,结束此轮遍历,同时 ++t,最上边界值向下移动一格并进行判断,若 t > b 则退出主循环;

从上到下:让索引 i = t,从上到下遍历直到 i > b,结束此轮遍历,同时 --r,最右边界值向左移动一格并进行判断,若 r < l 则退出主循环;

从右到左:让索引 i = r,从右到左遍历直到 i < l,结束此轮遍历,同时 --b,最下边界值向上移动一格并进行判断,若 b < t 则退出主循环;

从下到上:让索引 i = b,从下到上遍历直到 i < t,结束此轮遍历,同时 ++l,最左边界值向右移动一格并进行判断,若 l > r 则退出主循环;

直到主循环退出,返回收集好数据的列表即可

2.3 代码示例🌰

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {

        if (matrix.length == 0) {
            return new ArrayList<Integer>();
        }

        int t = 0, b = matrix.length - 1, l = 0, r = matrix[0].length - 1;
        List<Integer> list = new ArrayList<>();
        
        while (true) {

            for (int i = l;i <= r;i++) {
                list.add(matrix[t][i]);
            }
            if (++t > b) {
                break;
            }
            for (int i = t;i <= b;i++) {
                list.add(matrix[i][r]);
            }
            if (--r < l) {
                break;
            }
            for (int i = r;i >= l;i--) {
                list.add(matrix[b][i]);
            }
            if (--b < t) {
                break;
            }
            for (int i = b;i >= t;i--) {
                list.add(matrix[i][l]);
            }
            if (++l > r) {
                break;
            }
        }
        return list;
    }
}

3. 螺旋遍历二维数组(剑指Offer 146)

【题目链接】

3.1 思路分析🎯

这道题的解题思路与上道题(螺旋矩阵)基本一致

3.2 代码示例🌰

class Solution {
    public int[] spiralArray(int[][] array) {
        if (array.length == 0) {
            return new int[0];
        }

        int t = 0, b = array.length - 1, l = 0, r = array[0].length - 1;
        int[] arr = new int[(b + 1) * (r + 1)];
        int x = 0;
        while (true) {

            for (int i = l;i <= r;i++) {
                arr[x++] = array[t][i];
            }
            if (++t > b) {
                break;
            }
            for (int i = t;i <= b;i++) {
                arr[x++] = array[i][r];
            }
            if (--r < l) {
                break;
            }
            for (int i = r;i >= l;i--) {
                arr[x++] = array[b][i];
            }
            if (--b < t) {
                break;
            }
            for (int i = b;i >= t;i--) {
                arr[x++] = array[i][l];
            }
            if (++l > r) {
                break;
            }
        }
        return arr;
    }
}

以上便是对螺旋矩阵类型题的介绍了!!后续还会继续分享其它算法系列内容,如果这些内容对大家有帮助的话请给一个三连关注吧💕( •̀ ω •́ )✧( •̀ ω •́ )✧✨

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值