题目描述:
给你一个 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
解题准备:
1.了解可能存在的基础操作:本题要求按照顺时针螺旋返回数组中所有元素,本质就是按某种形式遍历数组所有元素,并且返回元素数据。
由于没有载体,所以要临时创建一个实例作为载体,即List<Integer>,实例初值为null,所以应添加数据。
11st.那么,就有两个操作:查找、添加。
2.纸上模拟操作,找一下规律:
明显可以发现,该遍历是从外到里,一层层遍历。
如果单独一层遍历,那么就满足先上、再右、再下、再左(边缘的划分条件可以自由抉择,我指的是:可以把0、0看成上,1、4、7看成右;;也可以把0、0、1看成上,4看成右,7、6、5看成下)
解题难点分析1:
本题最难的地方,不在于找出规律,而是如何用算法的语言,把规律描述出来。
1.最重要的第一步,是界定变量:需要用几个变量来描述规律,这些变量的作用分别是什么?
由上述的规律,我们假设攻破了一层,接下来的问题都迎刃而解(即,认为每一层都很完整,并且可以由第一层推导得到)
那么,第一层有四步:上、右、下、左。
上的遍历,只要求一个变量:top。由于行不变,仅列变,所以用top界定行正好,列可能需要一个变量temp1表示。
右的遍历,同样要求一个遍历:right、temp2。
同理,下:bottom;左:left。以及两个temp。
目前有8个变量,4个temp。
问题1:这些变量是否可以合并简化?
这个问题先放在一边,目前看不出能否简化。
问题2:这些变量,应该如何遍历每一层?
上:我们用top界定了行数,top初值为0(对于第一层,这个数为0,第二层,这个数为1,也就是每次遍历一层,都要top+1【遍历结果】),那么只要temp做好即可。【遍历得到matrix【top】【temp】】
temp如何界定?如果是第一层,明显是从0到column-1(列-1),第二层,则为1到column-2(列-2),用代码实现也不难,但是有点复杂,我们既然用left、right界定左右,那么能不能借助left、right呢?
右:用right界定列数,同理,遍历得到matrix【temp】【right】。temp,则需要用top和bottom界定。初值:column-1,遍历结果:right-1
下:同理,初值bottom为row-1,结果为bottom-1。
左:同理。初值:0,结果:left-1。
由于界定,每完整的一层,遍历得到的结果应该一致。(也就是不会遗漏、不会多出)
解题难点分析2:
目前我们知道,最内侧的一层,很可能不是完整的,比如3*3的矩阵(即本例),其中只有“上”,没有其它。
由于解题难点分析1已知,对于完整的一层,遍历结果一致,那么,对于残缺的一层,我们的重点应该在于,如何跳出循环?【其它的都一致,只要不多出重复元素,结果就符合题意】
也就是说,如何设定结束条件?【答案在下】
解题:
由于代码必然是迭代的,所以要求一致性,在这里按照下面的顺序进行遍历:
如图易得,上层的temp,从left开始,一直遍历到right;每次结束,top+1
右层temp,则从top开始,一直到bottom;同理
其它同理。
1.这里有有个问题:遍历总有结束,结束条件是什么?
如果从上下左右的关系来看,必然有top<=bottom,left<=right。【按照上述顺序遍历的解法,不太好写代码】
不过,由于该题要求遍历所有元素,而一个矩阵的元素有row*column==num个,所以只要遍历个数不达到num,都可以认为遍历未完成。
代码:
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
LinkedList<Integer> result = new LinkedList<>();
if(matrix==null||matrix.length==0) return result;
int top=0, left=0, bottom=matrix.length-1, right=matrix[0].length-1;
// 减1是因为从0开始数
int num = matrix.length*matrix[0].length;
// 这个条件,是指只要遍历到足够的数量,就退出。
while(num>0){
// temp<=的原因:只要在上层,都遍历
for(int temp=left; temp<=right && num>0; temp++){
result.add(matrix[top][temp]);
num--;
}
top++;
// temp<=的原因:top已经++,不担心top的重复,并且只要在右,都遍历
for(int temp=top; temp<=bottom && num>0; temp++){
result.add(matrix[temp][right]);
num--;
}
right--;
// temp>=的原因:right已经--,不担心right的重复,并且只要在下,都遍历
for(int temp=right; temp>=left && num>0; temp--){
result.add(matrix[bottom][temp]);
num--;
}
bottom--;
// temp>=的原因:bottom已经--,不担心bottom的重复,并且只要在左,都遍历
for(int temp=bottom; temp>=top && num>0; temp--){
result.add(matrix[temp][left]);
num--;
}
left++;
}
return result;
}
}
收尾:
易知,(四个temp、上下左右)8个变量都不好取舍,故都应该保留。
以上内容即我想分享的关于力扣热题4的一些知识。
我是蚊子码农,如有补充,欢迎在评论区留言。个人也是初学者,知识体系可能没有那么完善,希望各位多多指正,谢谢大家。