54. 螺旋矩阵
题目描述:给你一个 m 行 n 列的矩阵 matrix ,请按照顺时针螺旋顺序,返回矩阵中的所有元素。
题解:模拟即可。两种模拟方式:
- 直接模拟
- 按层模拟(转圈遍历)
直接模拟:设置方向数组,以及当前方向,以及4个方向的边界,每次更新坐标[i,j]
,若更新后越界,则切换到下一个方向
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
int n = matrix.length, m = matrix[0].length;
int[][] direction = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int directionIndex = 0; // 初始向右
List<Integer> ans = new ArrayList<>();
// 四个边界
int leftBoundary = 0, rightBoundary = m - 1, upBoundary = 0, bottomBoundary = n - 1;
// 当前坐标
int i = 0, j = 0;
while (i >= upBoundary && i <= bottomBoundary && j >= leftBoundary && j <= rightBoundary) {
ans.add(matrix[i][j]);
int ni = i + direction[directionIndex][0];
int nj = j + direction[directionIndex][1];
if (ni < upBoundary || ni > bottomBoundary || nj < leftBoundary || nj > rightBoundary) {
// 需要换方向了, 要更新边界
if (directionIndex == 0) upBoundary++;
else if (directionIndex == 1) rightBoundary--;
else if (directionIndex == 2) bottomBoundary--;
else leftBoundary++;
// 切换到下一个方向
directionIndex = (directionIndex + 1) % 4;
ni = i + direction[directionIndex][0];
nj = j + direction[directionIndex][1];
}
i = ni;
j = nj;
}
return ans;
}
}
按层模拟:
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
int n = matrix.length, m = matrix[0].length;
int total = n * m; // 总的数量
int top = 0, bottom = n - 1, left = 0, right = m - 1;
List<Integer> ans = new ArrayList<>();
int i = 0; // 计数
while (i < total) {
for (int j = left; j <= right && i < total; j++) {
ans.add(matrix[top][j]);
i++;
}
top++;
for (int j = top; j <= bottom && i < total; j++) {
ans.add(matrix[j][right]);
i++;
}
right--;
for (int j = right; j >= left && i < total; j--) {
ans.add(matrix[bottom][j]);
i++;
}
bottom--;
for (int j = bottom; j >= top && i <total; j--) {
ans.add(matrix[j][left]);
i++;
}
left++;
}
return ans;
}
}
59. 螺旋矩阵II
题目描述:给你一个正整数 n ,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
题解:和54类似,一个是遍历输出,一个是遍历填入。同样两种方式
- 直接模拟
- 按层模拟
直接模拟
class Solution {
public int[][] generateMatrix(int n) {
int[][] ans = new int[n][n];
int i = 0, j = 0;
int top = 0, bottom = n - 1, left = 0, right = n - 1;
int[][] d = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int di = 0; // direction
int idx = 1; // 填充的元素
while (i >= top && i <= bottom && j >= left && left <= right) {
ans[i][j] = idx++; // 填充到当前位置
int ni = i + d[di][0];
int nj = j + d[di][1];
if (ni < top || ni > bottom || nj < left || nj > right) {
if (di == 0) top++;
else if (di == 1) right--;
else if (di == 2) bottom--;
else left++;
di = (di + 1) % 4;
ni = i + d[di][0];
nj = j + d[di][1];
}
i = ni;
j = nj;
}
return ans;
}
}
按层模拟(一圈一圈填入):
class Solution {
public int[][] generateMatrix(int n) {
int[][] ans = new int[n][n];
int total = n * n;
int idx = 1;
int top = 0, bottom = n - 1, left = 0, right = n - 1;
while (idx <= total) {
for (int i = left; i <= right && idx <= total; i++) ans[top][i] = idx++;
top++;
for (int i = top; i <= bottom && idx <= total; i++) ans[i][right] = idx++;
right--;
for (int i = right; i >= left && idx <= total; i--) ans[bottom][i] = idx++;
bottom--;
for (int i = bottom; i >= top && idx <= total; i--) ans[i][left] = idx++;
left++;
}
return ans;
}
}