模拟矩阵路径进行遍历

题目链接-来源:力扣(LeetCode)

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

示例 1:

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

思路:

由于矩阵形状相当规则,所以模拟顺时针方向遍历并不困难。关键点在于,决定何时转向,以及转向哪个方向,还有最终在何时停止。
转向的时机:我们可以先判定当前前进方向上的下一个位置是否「可达」。首先需要维护一个同样大小的 visited[][] 矩阵,记录访问过的位置,若访问过,则「不可达」。另外,当下个位置发生数组越界时,同样不可达。这样我们只要在「不可达」时转向,「可达」时前进即可。
方向确定:为了使代码简单,不至于对4个方向都做一次判断,我们可以维护一个类似时钟指针一样顺时针旋转的向量数组 directions[][],这个数组里存储4个方向上的方向向量,例如, {0,1} 表示当前前进方向是上方。每次需要转向时,指针前进一位并对 4(数组长度) 求余即可进入下个方向。
终止条件:我们可以计数输出的数字个数,当个数达到要求时停止。
时间复杂度:O(mn)
空间复杂度:O(mn)

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public int[] spiralOrder(int[][] matrix) {
int height = matrix.length;
int width = height == 0 ? 0 : matrix[0].length;
int len = height * width;
int[] ans = new int[len];
boolean[][] visited = new boolean[height][width];

int[][] dirGroup = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int direction = 0;

int top = 0, bottom = height - 1, left = 0, right = width - 1;
int row = 0, col = 0;
for (int i = 0; i < len; i++) {
ans[i] = matrix[row][col];
visited[row][col] = true;
int nextRow = row + dirGroup[direction][0], nextCol = col + dirGroup[direction][1];
if (nextRow >= height || nextCol >= width || nextRow < 0 || nextCol < 0 || visited[nextRow][nextCol]) {
direction = (direction + 1) % 4;
}
row += dirGroup[direction][0];
col += dirGroup[direction][1];
}
return ans;
}
}