题目描述
给定M×N个元素的矩阵(M行,N列),以顺时针的方向返回矩阵的所有元素。
解题思路1
我一开始思路和我的上一篇498- Diagonal Traverse有些相似之处,都是按照一定的方式遍历一个矩阵,不同的是这道题需要判断下一坐标是否遍历过,通过定义一个visited数组就可以实现。
参考代码1
class Solution {
private int n;
private int m;
private int[][] visited; // 判断坐标是否遍历过
public List<Integer> spiralOrder(int[][] matrix) {
if(matrix.length == 0)
return null;
List<Integer> result = new ArrayList<>();
n = matrix.length;
m = matrix[0].length;
visited = new int[n][m]; // 数组初始化值全为0
int nextX, nextY;
int x = 0, y = 0;
// 顺时针四个方向,→ ↓ ← ↑,当前方向
int[] go = {1, 2, 3, 4};
int now = 0;
do {
result.add(matrix[x][y]);
visited[x][y] = 1;
// 方向 →
if (go[now] == 1) {
nextY = y + 1;
if (inArea(x, nextY) && !isVisited(x, nextY)) {
y++;
} else {
// 改变方向
now = ++now % 4;
x++;
}
} else if (go[now] == 2) {
nextX = x + 1;
if (inArea(nextX, y) && !isVisited(nextX, y)) {
x++;
} else {
now = ++now % 4;
y--;
}
} else if (go[now] == 3) {
nextY = y - 1;
if (inArea(x, nextY) && !isVisited(x, nextY)) {
y--;
} else {
now = ++now % 4;
x--;
}
} else if (go[now] == 4) {
nextX = x - 1;
if (inArea(nextX, y) && !isVisited(nextX, y)) {
x--;
} else {
now = ++now % 4;
y++;
}
}
} while (result.size() != n * m);
return result;
}
// 判断坐标是否在数组内
boolean inArea(int x, int y) {
return x >= 0 && x < n && y >= 0 && y < m;
}
// 判断下一坐标是否已经遍历过
boolean isVisited(int x, int y) {
return visited[x][y] == 1;
}
}
解题思路2(剑指Offer 29)
今天看剑指offer就刚好遇到了这题。。。
解决这道题的关键在于先形成清晰的思路,并把复杂的问题分解成若干个简单的问题。
- 把矩阵想象成若干个圈,每次从外到内依次遍历一圈 , 每次遍历都是从行坐标和列坐标相等的坐标开始遍历(start, start)。
- 结束条件 : result.size() > rows * columns ;
也可以根据行坐标、列坐标和行数、列数的关系来判断:如果行坐标 * 2 大于等于行数的话,那么当前坐标的下一列一定已经遍历过了,此时遍历结束,同理列坐标也一样,于是得到 columns > start * 2 && rows > start * 2
- 每次遍历一圈需要四步,从左到右,从上到下,从右到左,从下到上,每一步可以根据起始坐标和终止坐标完成遍历;
- 但是遍历最后一圈时,可能只需走三步,两步甚至一步。
- 遍历每一步的前提条件 :第一步是必须的;第二步前提是终止行号大于起始行号;第三步前提是终止行号大于起始行号,终止列号大于起始列号;第三步前提是终止行号比起始行号大2,同时终止列号大于起始列号。
参考代码2
class Solution2 {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
if (matrix.length == 0) {
return result;
}
int rows = matrix.length;
int columns = matrix[0].length;
int start = 0;
// while (columns > start * 2 && rows > start * 2) { //
while (result.length <= rows * columns) {
int endX = columns - 1 - start;
int endY = rows - 1 - start;
// 从左到右打印一行
for (int i = start; i <= endX; i++) {
result.add(matrix[start][i]);
}
// 从上到下打印一行
if (start < endY) {
for (int i = start + 1; i <= endY; ++i) {
result.add(matrix[i][endX]);
}
}
// 从右到左打印一行
if (start < endX && start < endY) {
for (int i = endX - 1; i >= start; i--) {
result.add(matrix[endY][i]);
}
}
// 从上到下打印一行
if (start < endX && start < endY - 1) {
for (int i = endY - 1; i >= start + 1; i--) {
result.add(matrix[i][start]);
}
}
start++;
}
return result;
}
}