给定一个包含 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 spiralOrder(int[][] matrix) {
ArrayList 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 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 spiralOrder(int[][] matrix) {
if (matrix.length == 0) {
return new ArrayList<>();
}
List 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 printItem(int[][] matrix, int r1, int c1, int r2, int c2, List 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/