假设有一个5 x 4的二维矩阵,现需要按照顺时针方向将其螺旋遍历,返回数组中的元素:
若二维数组如上所述,则其顺时针螺旋遍历的结果为:1、2、3、4、5、10、15、20、19、18、17、16、11、6、7、8、9、14、13、12。
其实,二维数组的元素排列很像汉字的“回”。“回”字由一个大矩形包裹着一个小矩形,而二维数组也可以看成是外围的若干元素包裹着内部的元素,由外向内层层嵌套起来。
那么我们完全可以按照一定的顺序从外向内一层一层遍历,就等同于对二维数组进行螺旋遍历了。
我们可以把二维数组的每一层拆解成上下左右4条边,然后按照顺时针方向遍历上、右、下、左即可。
当然,需要注意的是在遍历同一层的4条边时,要避免重复遍历矩形的4个角,即需要注意外层的1、5、20、16和内层的7、9、14、12元素。还有,当二维数组的最内层只剩下一行或者一列的时候,最内层遍历不再是上下左右4条边。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class test {
public static List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list = new ArrayList<Integer>();
//当二维数组是空或任何一个维度是0,直接返回
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return list;
}
//m是矩阵的行数
int rows = matrix.length;
//n是矩阵的列数
int columns = matrix[0].length;
//二维数组的层数,取决于行和列的较小值
int size = (Math.min(rows, columns)+1)/2;
//大循环,从外向内逐层遍历矩阵
for(int i=0; i < size; i++) {
//从左到右遍历“上边”
for (int j = i; j < columns - i; j++) {
list.add(matrix[i][j]);
}
//从上到下遍历“右边”
for (int j = i + 1; j < rows - i; j++) {
list.add(matrix[j][(columns - 1)-i]);
}
//从右到左遍历“下边”
for (int j = i + 1; j < columns - i && (rows - 1) - i > i; j++) {
list.add(matrix[(rows - 1)-i][(columns - 1) - j]);
}
//从下到上遍历“左边”
for (int j = i + 1; j < rows - 1 - i && i < (columns - 1)-i; j++) {
list.add(matrix[(rows - 1) - j][i]);
}
}
return list;
}
public static void main(String[] args) {
int[][] matrix = {
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 13, 14, 15 },
{ 16, 17, 18, 19, 20 }
};
int[][] matrix2 = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 },
{ 10, 11, 12 },
{ 13, 14, 15 }
};
List<Integer> List1 = spiralOrder(matrix);
System.out.println(Arrays.toString(List1.toArray()));
List<Integer> List2 = spiralOrder(matrix2);
System.out.println(Arrays.toString(List2.toArray()));
}
}
代码来源:https://mp.weixin.qq.com/s/FcCALo3tKWZpP2FE_16R5g