矩阵回型遍历
0. 如何操作矩阵(二维数组)
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
1. 题目分析
原题: 牛客网:顺时针打印矩阵.
1.1 画图
简单来说就是需要将一个矩阵以回字形打印出来,我们来把图画一下:
-
正常情况:

以上是常规情形,但凡事总会有例外,我们来看一下特殊情形:
- 只有一行的情况:

-
只有一列的情况:

当然了还有一种情况属于2.与3.重叠的情况,即只有一个元素,这里就不罗嗦了。
1.2 遍历的方式
既然是矩阵就得遍历对吧?那么我们可以采用什么样的方式来遍历呢?
-
纵向横向均衡地遍历,即每次遍历总是留空最后一个位置,这样的好处在于对称每次“转向”的改动都不大,即不用可以修改指针的方向:

-
第二种方法属于横向优先,即先完整地遍历完一横,再对列进行补充,这样做的好处在于可以很直观地解决
只有一行的情况,同理,纵向优先也可以很好地解决只有一列的情况:
-
第三种方法属于
1.和2.的综合,如图所示:
分析:
在方法一中,由于定义的限制,将会出现如下情况:
-
无法遍历到最后一个元素:

-
无法遍历最后一个元素:

所以排除了方法一
-
1.3 如何限定遍历的顺序?或者是遍历的方向?
如何界定遍历的界限?
第一种方法:定义四个变量,分别是left right top bottom

第二种方法:定义一个变量board,作为边界的变量

1.4 如何确定结束条件?
方法一:对应上面的第一种方法,即只有当 left<right && bottom<top。
若只有left<right,此时将不能保证只有一列的情况,
因为如果只有一列,此时left==right,循环已经结束,但是还有一整列的元素没有遍历到!
bottom<top同理。
方法二:对应上面的第二种方法,即只有当board的值落在矩阵的右下角才结束,判定条件为:
board<matrix.length-matrix.length/2 && board<matrix[0].length-matrix[0].length/2
实际上没有那么复杂,可以这样理解
matrix.length-matrix.length/2 = matrix.length%2==0?matrix.length/2:matrix.length/2+1
如图:

2. 实现代码
/**
方法一,设置border值,以上图的遍历顺序遍历
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer>();
int board = 0;//边界
int colLen = matrix[0].length;//列数
int rowLen = matrix.length;//行数
while(board<matrix.length-matrix.length/2 && board<matrix[0].length-matrix[0].length/2){
//从左到右
for(int i=board;i<colLen-board;i++){
list.add(matrix[board][i]);
}
//从上到下
for(int i=board+1;i<rowLen-board;i++){
list.add(matrix[i][colLen-1-board]);
}
//从右到左
if(rowLen-1-board>board){//判断上边界是否小于下边界
for(int i=colLen-1-board-1;i>board;i--){
list.add(matrix[rowLen-1-board][i]);
}
}
//从下到上
if(board<colLen-1-board){//判断左边界是否小于有边界
for(int i=rowLen-1-board;i>board;i--){
list.add(matrix[i][board]);
}
}
board++;
}
return list;
}
}
/**
方法二
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> list = new ArrayList<Integer>();
int left = 0;//左边界
int right = matrix[0].length-1;//右边界
int top = 0;//上边界
int bottom = matrix.length-1;//下边界
while(bottom+1>top && right+1>left){
//从左到右
for(int i=left;i<=right;i++){
list.add(matrix[top][i]);
}
//从上到下
for(int i=top+1;i<=bottom;i++){
list.add(matrix[i][right]);
}
//从右到左
if(bottom>top){//判断上边界是否小于下边界
for(int i=right-1;i>left;i--){
list.add(matrix[bottom][i]);
}
}
//从下到上
if(right>left){//判断左边界是否小于有边界
for(int i=bottom;i>top;i--){
list.add(matrix[i][left]);
}
}
left++;
right--;
top++;
bottom--;
}
return list;
}
}
3. 总结
- 先画图寻找可能的遍历方法…
- 确定好有效的遍历方法
- 确定遍历结束条件


7906

被折叠的 条评论
为什么被折叠?



