【每日刷题】螺旋矩阵

54. 螺旋矩阵 - 力扣(LeetCode)

先放自己写了好久的模拟代码,自己都被 i 和 j 搞晕了T_T最后还要特判,如果行和列的最小值为奇数,特殊处理一下最中心的数字。更详细的解释放在下面官方题解的代码上。这里对应的是官方题解的方法二“按层遍历”。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int m = matrix.length, n = matrix[0].length;
        int turn = Math.min(m, n) / 2;
        for(int i = 0; i < turn; i++) { //需要转圈的次数
            for(int j = i; j < n - i; j++) { //遍历上
                res.add(matrix[i][j]);
            }
            for(int j = i + 1; j < m - i; j++) { //遍历右
                res.add(matrix[j][n-1-i]);
            }
            for(int j = n - 2 -i; j >= i; j--) { //遍历下
                res.add(matrix[m-1-i][j]);
            }
            for(int j = m - 2 - i; j > i; j--) { //遍历左
                res.add(matrix[j][i]);
            }
        }
        if(turn * 2 != m && turn * 2 != n) {
            if(m > n) {
                for(int i = turn; i < m - turn; i++){
                    res.add(matrix[i][n/2]);
                }
            } else {
                for(int i = turn; i < n - turn; i++){
                    res.add(matrix[m/2][i]);
                }
            }
        }
        return res;
    }
}

看完自己的一大堆,再看官方的长代码都觉得眉清目秀了呢【bushi】其实两份代码思路是一样的,将矩阵看成若干层,先输出最外面一圈,接着继续输出第二圈,直到遍历结束。

依据题意,对于每层,从左上方开始顺时针遍历所有元素。当前层的左上角的坐标设为 (top, left),右下角坐标设为 (bottom, right)。角落处的数字在哪一侧遍历都可以,只要保证不会重复遍历即可(这里我跟官方题解稍微有一点出入)。

  • 遍历上侧,(top, left) 到 (top, right)
  • 遍历右侧,(top + 1, right) 到 (bottom, right)
  • 遍历下侧,(bottom, right - 1) 到 (bottom, left)
  • 遍历左侧,(bottom - 1, left ) 到 (top + 1, left)

遍历完当前层的元素之后,将 left 和 top 分别增加 1,将 right 和 bottom 分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。需要额外注意最中心的那层,如果是单行或者单列,会重复遍历。所以在遍历下侧和遍历左侧时,需要前提条件:如果 left < right 且 top < bottom 才遍历。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<Integer>();
        int rows = matrix.length, columns = matrix[0].length;
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while(left <= right && top <= bottom) {
            for(int i = left; i <= right; i++) {
                res.add(matrix[top][i]);
            }
            for(int i = top + 1; i <= bottom; i++) {
                res.add(matrix[i][right]);
            }
            if(left < right && top < bottom) {
                for(int i = right - 1; i >= left; i--) {
                    res.add(matrix[bottom][i]);
                }
                for(int i = bottom - 1; i > top; i--) {
                    res.add(matrix[i][left]);
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值