[LeetCode 54] 螺旋矩阵

题目描述

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:

输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

题目分析

这个题目难度并不大,还是很好想的,就跟着螺旋的方式来走。首先从第一行,接着就是最后一列,然后最后一行,最后就是最后一列。思路很清晰,就是坐标很容易搞混。

源码

class Solution{
public List<Integer> spiralOrder(int[][] matrix) {
    ArrayList<Integer> list = new ArrayList<>();
    if(matrix == null || matrix.length == 0) {
        return list;
    }
  
    int n = Math.min(matrix.length >> 1,matrix[0].length >> 1);
    //判断行列的大小
    if(n == 0) {
        for (int[] a: matrix) {
            for (int x:a) {
                list.add(x);
            }
        }
        return list;
    }
    boolean[][] flag = new boolean[matrix.length][matrix[0].length];
    for (int i = 0; i <= n; i++) {
        add(list,matrix,i,flag);
    }
    return list;
}

private void add(ArrayList<Integer> list, int[][] matrix, int k,boolean[][] flag) {
    //加入第一行
    for (int j = k; j < matrix[k].length-k; j++) {
        if(!flag[k][j]) {
            list.add(matrix[k][j]);
            flag[k][j] = true;
        }
    }

    //加入最后一列
    for (int j = k+1; j < matrix.length - k - 1; j++) {
        if(!flag[j][matrix[0].length - k - 1]){
            list.add(matrix[j][matrix[0].length - k - 1]);
            flag[j][matrix[0].length - k - 1] = true;
        }
    }
    //加入倒数第一行
    for (int j = matrix[0].length - 1 - k; j > k; j--) {
        if(!flag[matrix.length - 1 - k][j]){
            list.add(matrix[matrix.length - 1 - k][j]);
            flag[matrix.length - 1 - k][j] = true;
        }
    }
    //加入第一列
    for (int j = matrix.length - k - 1; j > k; j--) {
        if(!flag[j][k]) {
            list.add(matrix[j][k]);
            flag[j][k] = true;
        }
    }

}
}

改进

上面的方法肯定很好理解,但是还会有更好的办法。我可以从两个点开始,左上方和右下方的点,然后打印好外层之后可以再向里面打印。直到最后归位同一点就行啦

改进代码

class Solution{
public List<Integer> spiralOrder(int[][] matrix) {
    if (matrix.length == 0) {
        return new ArrayList<>();
    }
    List<Integer> res = new ArrayList<>();
    int h = matrix.length - 1;
    int l = matrix[0].length - 1;
    int r1 = 0;
    int c1 = 0;
    int r2 = h;
    int c2 = l;
    //取坐上的点和右下的点
    while (r1 <= r2 && c1 <= c2) {
        printItem(matrix, r1++, c1++, r2--, c2--, res);
    }
    //遍历整个最外层
    return res;
}

private List<Integer> printItem(int[][] matrix, int r1, int c1, int r2, int c2, List<Integer> res) {
    if (r1 == r2) {
        for (int i = c1; i <= c2; i++) {
            res.add(matrix[r1][i]);
        }
    } else if (c1 == c2) {
        for (int i = r1; i <= r2; i++) {
            res.add(matrix[i][c1]);
        }
        //n=0时
    } else {
        int r = r1;
        int c = c1;
        while (c < c2) {
            res.add(matrix[r1][c++]);
        }
        while (r < r2) {
            res.add(matrix[r++][c2]);
        }
        while (c > c1) {
            res.add(matrix[r2][c--]);
        }
        while (r > r1) {
            res.add(matrix[r--][c1]);
        }
    }
    return res;
}
}

分析

第一个的时间复杂度为O(n),因为空间复杂度很高
第二个的时间复杂度为O(n*m)

难点

这题的难点就是必须要好好的思考这些点的坐标位置,然后再慢慢向里推进。不仅可以用递归做,也可以的直接暴力循环。就看是牺牲空间复杂度还是牺牲时间复杂度啦。

小结

这题目并不太难,毕竟一看到题目之后就大致了解了思路。暴力循环是一种选择,毕竟时间复杂度不高,但是也要考虑到空间的存储。

[1]https://leetcode-cn.com/problems/spiral-matrix/submissions/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值