力扣经典算法篇-40-螺旋矩阵(方向遍历:方向数组+已访问元素集合)
1、题干
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入: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
2、解题
方法一:(方向遍历:方向数组+已访问元素集合)
本题要按照顺时针的方向遍历已有的二维数组。
思路:遍历数组,沿着一个方向添加数据,当达到切换方向条件时,切换方向添加数据,直到最终达到最大次数。
第一,因为要顺时针遍历,不是顺序遍历的规律,所以不可使用二层for循环遍历原始数据,需要记录原始二维数组的两个索引值进行遍历,索引值要根据规律去逐步更新。
第二,注意方向变化的规律。下一个元素如果越界就需要切换方向。如:小于0或大于最大列或行等情况。当然遇到已经访问过的元素也需要切换方向,所以这里还需要一个临时和原始数组一模一样的二维boolean数组来记录访问过的元素。
第三,方向的控制需要借助一个固定的二维数组{0, 1}, {1, 0}, {0, -1}, {-1, 0}代表右,下,左,上的四个方向。注意方向不能越界,可以加1后,对4取余数的方式获取新的方向。
代码示例:
import java.util.ArrayList;
import java.util.List;public class Test46 {public static List<Integer> spiralOrder(int[][] matrix) {List<Integer> result = new ArrayList<>();// 防止空元素if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {return result;}int rows = matrix.length; // 行数int cols = matrix[0].length; // 列数int count = rows * cols; // 行数*列数 = 最大遍历次数int dirIndex = 0; // 方向索引int[][] dirArr = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 方向集合。 右,下,左,上int index1 = 0, index2 = 0; // 元素索引boolean[][] visited = new boolean[rows][cols]; // 已遍历过元素的标记留痕for (int i = 0; i < count; i++) { // 这里不用while循环,用count作为做大循环处理更安全。// 添加元素result.add(matrix[index1][index2]);visited[index1][index2] = true;// 校验方向是否改变int nextIndex1 = index1 + dirArr[dirIndex][0];int nextIndex2 = index2 + dirArr[dirIndex][1];if (nextIndex1 < 0 || nextIndex1 >= rows || nextIndex2 < 0 || nextIndex2 >= cols || visited[nextIndex1][nextIndex2]) {dirIndex++;dirIndex = dirIndex % 4;}// 获取下一个元素值index1 = index1 + dirArr[dirIndex][0];index2 = index2 + dirArr[dirIndex][1];}return result;}public static void main(String[] args) {int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};System.out.println(spiralOrder(matrix));}
}
向阳前行,Dare To Be!!!