螺旋矩阵
个人社区:编程开发及计算机视觉成长手册
个人主页:NorthSmile
个人码云主页:https://gitee.com/northsmile
零、算法流程
0.基本对比
先对两道题的目的做一个对比:
- LeetCode59的要求通过给定的整数n顺时针生成合适的矩阵matrix,该矩阵的形状一定是n*n;
- LeetCode54要求将给定的矩阵matrix沿着顺时针反向依次输出所有元素,该矩阵形状为m*n,且m不一定等于n;
1.LeetCode59算法流程
从LeetCode59出发分析这两道题的一个解题思路,实际就是简单模拟螺旋路线:对于n来说只有奇数或者偶数两种情况,每次顺时针走完完整一遍经历四种操作,而我们的模拟过程就是重复进行以下四种操作:
- 自左向右;
- 自上向下;
- 自右向左;
- 自下向上;
我们需要解决的就是控制每次完整顺时针遍历过程中每个方向的起点及终点的边界问题,此处我分别用left、right、top、bottom四个变量控制对应的左右上下四个边界,先列出算法流程:
- a)初始化大小为n*n的全零矩阵matrix;
- b)初始化边界控制变量left=0,right=n-1,top=0,bottom=n-1;
- c)初始化i=left,自左向右填充matrix[top][i]的所有元素,其中i<=right,然后令top–,更新top移至下一行;
- d)初始化j=top,自上向下填充matrix[j][right]的所有元素,其中i<=bottom,然后令right–,更新right移至前一列;
- e)初始化k=right,自右向左填充matrix[bottom][k]的所有元素,其中k>=left,然后令bottom–,更新bottom移至上一行;
- f)初始化z=bottom,自上向下填充matrix[z][left]的所有元素,其中z>=top,然后令left++,更新left移至下一列;
- g)重复执行(c-f),直到left>right或者top>bottom说明所有元素已经填充完毕,因此停止循环,得到期望矩阵matrix;
1)n=3,初始化left=0,right=n-1=2,top=0,bottom=n-1=2,
2)n=4,初始化left=0,right=n-1=3,top=0,bottom=n-1=3,
2.LeetCode54算法流程
这道题是将给定的矩阵matrix所有元素按照顺时针顺序输出,与上面的生成问题可以看做是互逆操作。本题的解决思路也是简单模拟,重复执行上面提到的四种操作,直到达到边界条件说明所有元素已经遍历完成,停止遍历即可。
算法流程:分别用left、right、top、bottom四个变量控制对应的左右上下四个边界,先列出算法流程:
输入矩阵matrix大小为m*n,其中m与n不一定相等,二者之间大小关系不固定,因此边界考虑同上题相比需要考虑的更多一点。
- a)初始化m=matrix.lenth表示行数,n=matrix[0].length表示列数;
- b)初始化边界控制变量left=0,right=n-1,top=0,bottom=m-1;
- c)首先判断此时是否越界,即是否满足top<=bottom且left<=right,否则停止遍历;
- d)初始化i=left,自左向右输出matrix[top][i]的所有元素,其中i<=right,然后令top–,更新top移至下一行;判断此时top是否超出bottom,即top>bottom;
- e)初始化j=top,自上向下输出matrix[j][right]的所有元素,其中j<=bottom,然后令right–,更新right移至前一列;判断此时left是否超出right,即left>right;
- f)初始化k=right,自右向左输出matrix[bottom][k]的所有元素,其中k>=left,然后令bottom–,更新bottom移至上一行;
- g)初始化z=bottom,自上向下输出matrix[z][left]的所有元素,其中z>=top,然后令left++,更新left移至下一列;
- h) 重复执行(c-g);
注意:我上面说的输出对应元素放在LeetCode54中即指将该元素添加到结果集合中,代码中有所体现。
1)m=2,n=3,m<n
2)m=3,n=3,m=n,且m为奇数
2)m=3,n=4,m<n
4)m=4,n=4,m=n,且m为偶数
一.LeetCode59:螺旋矩阵II
1)题目内容
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
原题链接:https://leetcode.cn/problems/spiral-matrix-ii/
2)样例
3)核心代码
class Solution {
// 模拟
public static int[][] generateMatrix(int n) {
int[][] matrix=new int[n][];
for (int i=0;i<n;i++){ // 初始化矩阵为全0矩阵
matrix[i]=new int[n];
}
int left=0,right=n-1,top=0,bottom=n-1; // 定义边界变量
int num=1; // 计数
while (true){
if (left>right||top>bottom){
break;
}
// 1.左->右
int i=left;
while (i<=right){
matrix[top][i++]=num++;
}
top++;
// 2.上->下
int j=top;
while (j<=bottom){
matrix[j++][right]=num++;
}
right--;
// 3.右->左
int k=right;
while (k>=left){
matrix[bottom][k--]=num++;
}
bottom--;
// 4.下->上
int z=bottom;
while (z>=top){
matrix[z--][left]=num++;
}
left++;
}
return matrix;
}
}
二.LeetCode54:螺旋矩阵
1)题目内容
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
原题链接:https://leetcode.cn/problems/spiral-matrix/
2)样例
3)核心代码
class Solution {
// 模拟
public static List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res=new ArrayList<>(); // 存储结果
int left=0,right=matrix[0].length-1,top=0,bottom=matrix.length-1; // 控制边界
while (true) {
if (top>bottom||left>right){
break;
}
// 1.左->右
int j = left;
while (j <=right) {
res.add(matrix[top][j++]);
}
top++;
if (top>bottom){
break;
}
// 2.上->下
int i = top;
while (i <=bottom) {
res.add(matrix[i++][right]);
}
right--;
if (left>right){
break;
}
// 3.右->左
int k = right;
while (k >= left) {
res.add(matrix[bottom][k--]);
}
bottom--;
// 4.下->上
int z = bottom;
while (z >= top) {
res.add(matrix[z--][left]);
}
left++;
}
return res;
}
}