模拟法
- 首先,需要确定定义边界的规则,从而确定模拟的区间,比如采用左闭右开,左闭右闭等。本题建议采用左闭右开,也就是起点闭合,终点打开。
- 其次,循环次数也很重要,用来确定模拟什么时候结束。本题没转一圈是走2行和2列,因此模拟次数为行数和列数中最小值的一半。
- 如果为奇数行或奇数列,每次走2行2列,最后会剩下1行或1列,因此最后需要模拟打印剩下的1行或一列。
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> spiralOrder(int[][] matrix) {
ArrayList<Integer> res = new ArrayList<>();
if(matrix == null || matrix.length == 0)
return res;
int m = matrix.length, n = matrix[0].length;
int loop = Math.min(m / 2, n /2); // 循环次数
int startx = 0, starty = 0;
int offset = 1; // 偏移量
int i,j;
// 参考代码随想录:区间[起点,终点),左闭右开
for(int c = 0; c < loop; c++){
i = startx;
j = starty;
// 上
while(j < starty + n - offset){
res.add(matrix[i][j]);
++j;
}
// 右
while(i < startx + m - offset){
res.add(matrix[i][j]);
++i;
}
// 下
while(j > starty){
res.add(matrix[i][j]);
j--;
}
// 左
while(i > startx){
res.add(matrix[i][j]);
i--;
}
startx++;
starty++;
offset += 2; //因为startx和starty也加了1,所以计算边界时需要将其减掉
}
if(Math.min(m, n) % 2 == 1){ // 每次走2行2列,所以奇数行或奇数列最后会剩下一行或一列
i = startx;
j = starty;
if(m <= n){
// 剩下一行
for(; j <= starty + n - offset; j++){
res.add(matrix[i][j]);
}
} else {
// 剩下一列
for(; i <= startx + m - offset; ++i)
res.add(matrix[i][j]);
}
}
return res;
}
}