【leetcode常见面试题】螺旋矩阵解题思路

螺旋矩阵

在这里插入图片描述

解题思路

本题可以采用模拟的方式,设4种行走方向,如下图:

先找行进路线

4个方向的行走路线分别是:从左到右,从上到下,从右到左,从下到上。

并且
从左到右是从第一行开始,
从上到下是从最后一列开始,
从右到左是从最后一行开始,
从下到上是从第一列开始。

在这里插入图片描述

代码定义如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    return ans;
}

当第一圈走完以后,4个方向一定都会向内收缩一圈。

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 第一行走完
    leftToRight++;
    // 最后一列走完
    upToDown--;
    // 最后一行走完
    rightToLeft--;
    // 第一列走完
    downToUp++;
    return ans;
}

找每条路线的结束位置

现在我们只需要搞清楚如何定义每个方向算走完这个逻辑即可,从图上可以看出,每个方向的结束位置,就是下一个方向的开始位置,比如从左向右走时,行保持不变,列应该一直走到下一个方向的开始位置,即upToDown定义的范围。
从上到下走时,列保持不变,行应该一直走到下一个方向的开始位置,即rightToLeft定义的范围。

由此可得,如下代码:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    
    // 1. 从左到右
    for(int i = ?; i <= upToDown; i++){
    }
    // 从左到右走完
    leftToRight++;
    
    // 2. 从上到下
    for(int i = ?; i <= rightToLeft; i++){
    }
    // 从上到下走完
    upToDown--;
    
    // 3. 从右到左
    for(int i = ?; i >= downToUp; i--){
    }
    // 从右到左走完
    rightToLeft--;
    
    // 4. 从下到上
    for(int i = ?; i >= leftToRight; i--){
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

再找每条路线的结束位置

弄清楚4个方向的结束位置之后,剩下来的只要在定义好开始位置就好了,很明显,上一个方向的结束位置,即是当前方向的开始位置。

所以,我们填入4个方向的开始值后,代码如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 1. 从左到右
    for (int i = downToUp; i <= upToDown; i++) {
    }
    // 从左到右走完
    leftToRight++;
    // 2. 从上到下
    for (int i = leftToRight; i <= rightToLeft; i++) {
    }
    // 从上到下走完
    upToDown--;
    // 3. 从右到左
    for (int i = upToDown; i >= downToUp; i--) {
    }
    // 从右到左走完
    rightToLeft--;
    // 4. 从下到上
    for (int i = rightToLeft; i >= leftToRight; i--) {
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

模拟行走

接下来,让每个方向走起来,并挨个添加到集合中,代码如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 1. 从左到右
    for (int i = downToUp; i <= upToDown; i++) {
        ans.add(matrix[leftToRight][i]);
    }
    // 从左到右走完
    leftToRight++;
    // 2. 从上到下
    for (int i = leftToRight; i <= rightToLeft; i++) {
        ans.add(matrix[i][upToDown]);
    }
    // 从上到下走完
    upToDown--;
    // 3. 从右到左
    for (int i = upToDown; i >= downToUp; i--) {
        ans.add(matrix[rightToLeft][i]);
    }
    // 从右到左走完
    rightToLeft--;
    // 4. 从下到上
    for (int i = rightToLeft; i >= leftToRight; i--) {
        ans.add(matrix[i][downToUp]);
    }
    // 从下到上走完
    downToUp++;
    return ans;
}

矩阵大小即是一共要走的步数,那么每走一步记录一下,直到走满矩阵大小即表示走完。

最后代码实现如下:

public List<Integer> spiralOrder(int[][] matrix) {
    // 结果集
    List<Integer> ans = new ArrayList<>();
    int step = 0;
    int totalStep = matrix.length * matrix[0].length;
    // 定义4个方向
    int leftToRight = 0;
    int upToDown = matrix[0].length - 1;
    int rightToLeft = matrix.length - 1;
    int downToUp = 0;
    // 外层while控制每一圈走完后,要不要继续走
    // 里面的每一个for控制每一步走完后,要不要继续走
    while (step < totalStep) {
        // 1. 从左到右
        for (int i = downToUp; i <= upToDown && step < totalStep; i++) {
            ans.add(matrix[leftToRight][i]);
            step++;
        }
        // 从左到右走完
        leftToRight++;
        // 2. 从上到下
        for (int i = leftToRight; i <= rightToLeft && step < totalStep; i++) {
            ans.add(matrix[i][upToDown]);
            step++;
        }
        // 从上到下走完
        upToDown--;
        // 3. 从右到左
        for (int i = upToDown; i >= downToUp && step < totalStep; i--) {
            ans.add(matrix[rightToLeft][i]);
            step++;
        }
        // 从右到左走完
        rightToLeft--;
        // 4. 从下到上
        for (int i = rightToLeft; i >= leftToRight && step < totalStep; i--) {
            ans.add(matrix[i][downToUp]);
            step++;
        }
        // 从下到上走完
        downToUp++;
    }
    return ans;
}

螺旋矩阵 II

使用同样的套路即可快速完成
在这里插入图片描述

public int[][] generateMatrix(int n) {
    int[][] ans = new int[n][n];
    int step = 0;
    int leftToRight = 0;
    int upToDown = n - 1;
    int rightToLeft = n - 1;
    int downToUp = 0;
    while (step < n * n) {
        for (int i = downToUp; i <= upToDown && step < n * n; i++) {
            ans[leftToRight][i] = ++step;
        }
        leftToRight++;
        for (int i = leftToRight; i <= rightToLeft && step < n * n; i++) {
            ans[i][upToDown] = ++step;
        }
        upToDown--;
        for (int i = upToDown; i >= downToUp && step < n * n; i--) {
            ans[rightToLeft][i] = ++step;
        }
        rightToLeft--;
        for (int i = rightToLeft; i >= leftToRight && step < n * n; i--) {
            ans[i][downToUp] = ++step;
        }
        downToUp++;
    }
    return ans;
}

总结

记住三个关键点即可:

  1. 总共上下左右4个方向。
  2. 每个方向的开始都由上一个方向的结束来决定。
  3. 每个方向的结束都由下一个方向的开始来决定。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值