剑指OfferJZ3219:顺时针打印矩阵-java版
JZ19:则依次打印出数字
[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
示例1
输入: [[1,2,3],[4,5,6],[7,8,9]]
返回值: [1,2,4,3]
我们可以把二维数组的每一层拆解为上下左右四条边,既然题目要求顺时针遍历,我们对边的访问顺序就应该是:上,右,下,左,也即是往右,往下,往左,往上
我们可以用flag变量来标记当前遍历矩阵的方向:
1:往右,2:往下,3:往左,4:往上
二维数组matrix的行数x为:matrix.length 列数y为:matrix[0].length
如图,
- 我们一开始往右走(y增加),此时flag=1,经过1->2->3->#,走到3以后的位置时越界(y=4),即超过了数组的列数y,更改flag=2,并消除数组越界y–,最后转向x++
-
接着往下走(x增加)此时flag=2,经过6->9->#,走到9以后的位置越界(x=4),即超过了数组的行数x,更改flag=3,并消除数组越界x–,最后转向y–
-
接着往左走(y减小)此时flag=3,经过8->7->#,走到7以后的位置越界(y=-1),即超过了数组的列数y,更改flag=4,并消除数组越界y++,最后转向x–
-
接着往上走(x减小)此时flag=4,经过4->1,走到1的位置发现1已经被遍历过了,也属于越界,那么我们将x增加回到4的位置,再将y增加转向到5的位置
到这里整个二维数组就走完了!
补充:
- :走到遍历过的数也属于越界
- :按以上步骤每走过没有越界的位置的数就把它存储到数组中,我这里是ans数组)
public class jz19{
public ArrayList<Integer> printMatrix(int [][] matrix) {
ArrayList<Integer> ans=new ArrayList<>();
int flag=1;//flag标记当前矩阵遍历的方向 1->往右,2->往下,3->往左,4->往上
int x=0;//矩阵的下标
int y=0;
boolean[][] vis=new boolean[matrix.length][matrix[0].length];//vis数组用来标记已经走过的点//matrix.length表示行数x,matrix[0].length表示列数y
while (ans.size()<matrix.length*matrix[0].length){//数组大小
if(x<0 || x>= matrix.length || y<0 || y>=matrix[0].length || vis[x][y]){//如果越界//vis[x][y]已经遍历过的位置,也当做越界处理
if(flag==1){//往右走,y(列数)增加
flag=2;//更新flag
y--;//消除越界的影响
x++;//本质上就是到达下一个位置的横坐标
}else if(flag==2){//往下走,x(行数)增加
flag=3;
x--;//消除越界的影响
y--;//本质上就是到达下一个位置的纵坐标
}else if(flag==3){//往左走,y(列数)减少
flag=4;
y++;//消除越界的影响
x--;//本质上就是到达下一个位置的横坐标
}else{//往上走,x(行数)减少
flag=1;
x++;//消除越界的影响
y++;//本质上就是到达下一个位置的纵坐标
}
}else {//如果未越界
ans.add(matrix[x][y]);
vis[x][y]=true;//去标记已经遍历过的位置
//根据flag的值更新遍历矩阵的下标x,y的值
if(flag==1){
y++;//往右走,y(列数)增加
}else if(flag==2){
x++;//往下走,x(行数)增加
}else if(flag==3){
y--;//往左走,y(列数)减少
}else{
x--;//往上走,x(行数)减少
}
}
}
return ans;
}
}