力扣记录:59 螺旋矩阵II及相关题目

本次题目

  • 59 螺旋矩阵II
  • 54 螺旋矩阵
  • 剑指Offer 29 顺时针打印矩阵

59 螺旋矩阵II

  • 螺旋循环为由外到内顺时针,注意循环的终止条件,循环次数为n/2向下取整(关于中心对称)。
  • 每次螺旋循环分为从左到右,从上到下,从右到左,从下到上的四条边,每条边也要注意循环终止的条件,左闭右开,循环次数为螺旋循环的边界减一。
  • 注意当n为奇数时,循环结束后要在中心补充最后一个元素。
class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];//定义二维数组存储结果
        int loop = n/2;//定义循环的圈数,中心对称
        //定义循环起始的下标
        int startX = 0;
        int startY = 0;
        int num = 1;//定义存入矩阵的数
        int count = n - 1;//定义循环中每条边的边界
        while(loop > 0){
            //定义填入的下标
            int i = startX;
            int j = startY;
            //循环的第一条边
            for(j = startY;j < count; j++){
                res[i][j] = num++;
            }
            //循环的第二条边
            for(i = startY;i < count; i++){
                res[i][j] = num++;
            }
            //循环的第三条边,从右到左!
            for(;j >startY; j--){
                res[i][j] = num++;
            }
            //循环的第四条边,从下到上!
            for(;i >startX; i--){
                res[i][j] = num++;
            }
            //准备下一次循环,循环起始下标增加,边界减小
            startX++;
            startY++;
            count -= 1;
            loop--;
        }
        //如果n为奇数,需要补充中心元素
        if(n % 2 == 1){
            int cen = n/2;
            res[cen][cen] = num;
        }
        return res;
    }
}

54 螺旋矩阵

  • 为上述题目的反向操作,注意两个循环的终止条件。由于矩阵不一定是方阵,因此螺旋循环的次数为min{m,n}/2向下取整。
  • 每次循环中四条边的终止条件分为左右和上下。
  • 当n为奇数时,中心位置可能是一行或一列或一个元素,起始位置与循环次数有关,每循环一次,中心的起始位置就向左(下)移动一个单位,终止位置就向右(上)移动一个单位。
class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int m = matrix.length;
        int n = matrix[0].length;
        int loop = Math.min(m/2, n/2) ;//定义循环的次数,取决于最短边
        //定义循环起始的下标
        int startX = 0;
        int startY = 0;
        int countLeftRight = n - 1;//定义循环中左右边的边界
        int countUpDown = m - 1;//定义循环中上下边的边界
        while(loop > 0){
            //定义循环遍历指向的下标
            int i = startX;
            int j = startY;
            //从左到右
            for(j = startY; j < countLeftRight; j++){
                res.add(matrix[i][j]);
            }
            //从上到下
            for(i = startX; i < countUpDown; i++){
                res.add(matrix[i][j]);
            }
            //从右到左
            for(; j > startY; j--){
                res.add(matrix[i][j]);
            }
            //从下到上
            for(; i > startX; i--){
                res.add(matrix[i][j]);
            }
            //准备下一次循环,循环起始下标增加,边界减小,循环次数减少
            startX++;
            startY++;
            countLeftRight--;
            countUpDown--;
            loop--;
        }
        //由于m不一定等于n,循环结束后的中心可能超过一个单位,因此分情况讨论
        if(m > n){//m大于n时中心为i*1矩阵
            if(n % 2 == 1){
                int cen = n/2;
                //cen=循环次数,每循环一次中心起始位置就往下一个单位,终止位置就往上一个单位
                for(int i = cen; i < m - cen; i++){
                    res.add(matrix[i][cen]);
                }
            }
        }else if(m < n){//m小于n时中心为1*j矩阵
            if(m % 2 == 1){
                int cen = m/2;
                //cen=循环次数,每循环一次中心起始位置就往右一个单位,终止位置就往左一个单位
                for(int j = cen; j < n - cen; j++){
                    res.add(matrix[cen][j]);
                }
            }
        }else{//m等于n时中心为1*1矩阵
            if(m % 2 == 1){
                int cen = n/2;
                res.add(matrix[cen][cen]);
            }
        }
        return res;
    }
}

剑指Offer 29 顺时针打印矩阵

  • 同(1),但是输入矩阵可能为空(m=0),返回数据类型为int[ ]。
class Solution {
    public int[] spiralOrder(int[][] matrix) {
        if(matrix.length == 0){
            int[] res = {};
            return res;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        int[] res = new int[m*n];
        int num = 0;//定义数组存储的下标
        int loop = Math.min(m/2, n/2) ;//定义循环的次数,取决于最短边
        //定义循环起始的下标
        int startX = 0;
        int startY = 0;
        int countLeftRight = n - 1;//定义循环中左右边的边界
        int countUpDown = m - 1;//定义循环中上下边的边界
        while(loop > 0){
            //定义循环遍历指向的下标
            int i = startX;
            int j = startY;
            //从左到右
            for(j = startY; j < countLeftRight; j++){
                res[num] = matrix[i][j];
                num++;
            }
            //从上到下
            for(i = startX; i < countUpDown; i++){
                res[num] = matrix[i][j];
                num++;
            }
            //从右到左
            for(; j > startY; j--){
                res[num] = matrix[i][j];
                num++;
            }
            //从下到上
            for(; i > startX; i--){
                res[num] = matrix[i][j];
                num++;
            }
            //准备下一次循环,循环起始下标增加,边界减小,循环次数减少
            startX++;
            startY++;
            countLeftRight--;
            countUpDown--;
            loop--;
        }
        //由于m不一定等于n,循环结束后的中心可能超过一个单位,因此分情况讨论
        if(m > n){//m大于n时中心为i*1矩阵
            if(n % 2 == 1){
                int cen = n/2;
                //cen=循环次数,每循环一次中心起始位置就往下一个单位,终止位置就往上一个单位
                for(int i = cen; i < m - cen; i++){
                    res[num] = matrix[i][cen];
                    num++;
                }
            }
        }else if(m < n){//m小于n时中心为1*j矩阵
            if(m % 2 == 1){
                int cen = m/2;
                //cen=循环次数,每循环一次中心起始位置就往右一个单位,终止位置就往左一个单位
                for(int j = cen; j < n - cen; j++){
                    res[num] = matrix[cen][j];
                    num++;
                }
            }
        }else{//m等于n时中心为1*1矩阵
            if(m % 2 == 1){
                int cen = n/2;
                res[num] = matrix[cen][cen];
                num++;
            }
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值