54. 螺旋矩阵: 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] 输出:[1,2,3,4,8,12,11,10,9,5,6,7]
提示:
m == matrix.length n == matrix[i].length 1 <= m, n <= 10 -100 <= matrix[i][j] <= 100
方法解析:模拟访问二维数组方向解法: (1)左 -> 右 (2)上 -> 下 (3)右 -> 左 (4)下 -> 上
动画显示参考连接:https://leetcode.cn/problems/spiral-matrix/solution/dong-hua-mo-ni-yi-xia-jiu-neng-gao-dong-i27qf/
int top = 0, bottom = row - 1; // 定义上下边界
int left = 0, right = column - 1; // 定义左右边界
while (true){
// 遍历二维数组的上边 行不变 列变化
for(int i = left; i <= right; i++){
ans[index++] = matrix[top][i];
}
top++; // 当前行遍历完全,移动到下一行
if(top > bottom) break; // 循环结束标志,这里不能取等号
// 遍历二维数组的右边 行变化 列不变
for(int i = top; i <= bottom; i++){
ans[index++] = matrix[i][right];
}
right--; // 右边遍历完全 向左边靠拢
if(right < left) break;
// 遍历二维数组的下边 行不变 列变化
for(int i = right; i >= left; i--){
ans[index++] = matrix[bottom][i];
}
bottom--; // 下边遍历完全,向上移动
if(bottom < top) break;
// 遍历二维数组的左边 行变化 列不变
for(int i = bottom; i >= top; i--){
ans[index++] = matrix[i][left];
}
left++; // 左边遍历完全 向左移动
if(left > right) break;
}
代码实现:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SpiralOrderDemo {
public static void main(String[] args) {
// int[][] matrix = {{1,2,3},{4,5,6},{7,8,9}};
int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int[] ans = spiralOrder1(matrix);
System.out.println(Arrays.toString(ans));
List list = spiralOrder2(matrix);
System.out.println(list);
}
public static int[] spiralOrder1(int[][] matrix){
int row = matrix.length; // 二维矩阵的行数
if(row == 0 || matrix == null){
return new int[]{}; // 空数组
}
int column = matrix[0].length; // 二维矩阵的列数
int[] ans = new int[row * column]; // 定义返回数组---大小为row * column
int index = 0; // ans数组下标
int top = 0, bottom = row - 1; // 定义上下边界
int left = 0, right = column - 1; // 定义左右边界
while (true){
// 遍历二维数组的上边 行不变 列变化
for(int i = left; i <= right; i++){
ans[index++] = matrix[top][i];
}
top++;
if(top > bottom) break;
// 遍历二维数组的右边 行变化 列不变
for(int i = top; i <= bottom; i++){
ans[index++] = matrix[i][right];
}
right--; // 右边遍历完全 向左边靠拢
if(right < left) break;
// 遍历二维数组的下边 行不变 列变化
for(int i = right; i >= left; i--){
ans[index++] = matrix[bottom][i];
}
bottom--; // 下边遍历完全,向上移动
if(bottom < top) break;
// 遍历二维数组的左边 行变化 列不变
for(int i = bottom; i >= top; i--){
ans[index++] = matrix[i][left];
}
left++; // 左边遍历完全 向左移动
if(left > right) break;
}
return ans;
}
public static List spiralOrder2(int[][] matrix){
List ans = new ArrayList<>();
int m = matrix.length, n = matrix[0].length;
circle(matrix, 0, 0, m-1, n-1, ans);
return ans;
}
static void circle(int[][] matrix, int x1, int y1, int x2, int y2, List ans){
if(x2 < x1 || y2 < y1){
return;
}
// 只有一行时, 按照行进行遍历
if(x1 == x2){
for(int i = y1; i <= y2; i++){
ans.add(matrix[x1][i]);
}
return;
}
// 只有一列时, 按照列进行遍历
if(y1 == y2){
for(int i = x1; i <= x2; i++){
ans.add(matrix[i][y1]);
}
return;
}
// 遍历当前圈
for(int i = y1; i < y2; i++) ans.add(matrix[x1][i]);
for(int i = x1; i < x2; i++) ans.add(matrix[i][y2]);
for(int i = y2; i > y1; i--) ans.add(matrix[x2][i]);
for(int i = x2; i > x1; i--) ans.add(matrix[i][y1]);
// 往里收一圈,继续遍历
circle(matrix, x1 + 1, y1 + 1, x2 - 1, y2 -1, ans);
}
}
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/spiral-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
59. 螺旋矩阵 II: 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入:n = 3 输出:[[1,2,3],[8,9,4],[7,6,5]]
示例 2:
输入:n = 1 输出:[[1]]
方法解析:
本题和螺旋矩阵非常相像,也可以理解成其进阶版,只要会了螺旋矩阵的访问方式就可以做本题。
public static int[][] generateMatrix(int n){
int[][] ans = new int[n][n];
int left = 0, right = n - 1; // 二维数组左右边界
int top = 0, bottom = n - 1; // 二维数组上下边界
int value = 1;
while (true){
// 上边
for(int i = left; i <= right; i++){
ans[top][i] = value; // 唯一改动的地方
value++;
}
top++;
if(top > bottom) break;
// 右边
for(int i = top; i <= bottom; i++){
ans[i][right] = value;
value++;
}
right--;
if(right < left) break;
// 下边
for(int i = right; i >= left; i--){
ans[bottom][i] = value;
value++;
}
bottom--;
if(top > bottom) break;
// 左边
for(int i = bottom; i >= top; i--){
ans[i][left] = value;
value++;
}
left++;
if(left > right) break;
}
return ans;
}
总结:
按照题目的要求发现该遍历方式很好理解,但是难点就在于对于边界的处理,通过参考别人写的题解发现要设置上下两个边界top = 0、bottom = row - 1, 左右两个边界 left = 0 和 right = column - 1。
当访问数组上边界后要进行top++操作,表示当前上边界已经遍历完全,还要进行top与bottom判断,循环结束的条件为top > bottom;
当访问数组有边界后要进行right--操作,表示当前右边界已经遍历完全,还要进行left与right判断,循环结束的条件为left > bottom;
当访问数组下边界后要进行bottom--操作,表示当前下边界已经遍历完全,还要进行top与bottom判断,循环结束的条件为top > bottom;
当访问数组左边界后要进行left操作,表示当前左边界已经遍历完全,还要进行left与right判断,循环结束的条件为left > bottom;
此题的解题技巧可以背下来!!!!



