这是一道难度为中等的题目,让我们来看看题目描述:
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
题解
解题的核心思路是按照右、下、左、上的顺序遍历数组,并使用四个变量圈定未遍历元素的边界:
随着螺旋遍历,相应的边界会收缩,直到螺旋遍历完整个数组:
class Solution {public List<Integer> spiralOrder(int[][] matrix) {// 获取矩阵的行数和列数int m = matrix.length; // 行数int n = matrix[0].length; // 列数// 定义遍历未处理区域的边界:// upper_bound:上边界,初始为第一行(索引0)// lower_bound:下边界,初始为最后一行(索引 m - 1)int upper_bound = 0, lower_bound = m - 1;// left_bound:左边界,初始为第一列(索引0)// right_bound:右边界,初始为最后一列(索引 n - 1)int left_bound = 0, right_bound = n - 1;// 创建一个链表用来保存最终的螺旋顺序遍历结果List<Integer> res = new LinkedList<>();// 当结果列表的元素个数还没有达到整个矩阵的元素总数时,继续遍历while (res.size() < m * n) {// 从左到右遍历上边界这一行// 前提条件:upper_bound <= lower_bound确保当前行未超出下边界if (upper_bound <= lower_bound) {for (int j = left_bound; j <= right_bound; j++) {res.add(matrix[upper_bound][j]); // 将上边界行的元素依次添加}upper_bound++; // 上边界向下移动一行,因为当前行已遍历}// 从上到下遍历右边界这一列// 前提条件:left_bound <= right_bound确保当前列未超出左边界if (left_bound <= right_bound) {for (int i = upper_bound; i <= lower_bound; i++) {res.add(matrix[i][right_bound]); // 将右边界列的元素依次添加}right_bound--; // 右边界向左移动一列,因为当前列已遍历}// 从右到左遍历下边界这一行// 前提条件:upper_bound <= lower_bound确保当前行未超出上边界if (upper_bound <= lower_bound) {for (int j = right_bound; j >= left_bound; j--) {res.add(matrix[lower_bound][j]); // 将下边界行的元素依次添加}lower_bound--; // 下边界向上移动一行,因为当前行已遍历}// 从下到上遍历左边界这一列// 前提条件:left_bound <= right_bound确保当前列未超出右边界if (left_bound <= right_bound) {for (int i = lower_bound; i >= upper_bound; i--) {res.add(matrix[i][left_bound]); // 将左边界列的元素依次添加}left_bound++; // 左边界向右移动一列,因为当前列已遍历}}// 返回包含所有元素的螺旋顺序结果列表return res;}
}
总结
这道题目的解法对我来说有一些难以理解,那么直接强制记忆:
你可以试着将这个螺旋遍历过程拆分成四个简单的步骤,每一步只关注一个方向,并记住一个顺时针的遍历顺序:从左到右、从上到下、从右到左、从下到上。下面几个记忆小技巧可能对你有帮助:
-
分块记忆:
想象矩阵就像一层层的“洋葱皮”。每一层的遍历就是围绕这个“洋葱”走一圈,你只需要记住当前层的边界,然后按照顺时针方向依次执行四个步骤。 -
口诀法:
你可以编一个简单的口诀,比如“左到右,上到底,右到左,下到上”。每完成一圈后,再调整边界,重复这个过程。 -
边界的概念:
四个变量(upper_bound、lower_bound、left_bound、right_bound)就像四道“防线”。每次遍历一条边之后,你就“消耗”掉这一行或这一列,然后更新边界。记住:-
遍历上边界后,upper_bound++
-
遍历右边界后,right_bound–
-
遍历下边界后,lower_bound–
-
遍历左边界后,left_bound++
-
-
可视化思维:
在心里或纸上画出一个矩阵,并用箭头标注出遍历的方向。通过不断的练习,你会发现这种螺旋移动方式会越来越直观。