剑指OfferJZ19:顺时针打印矩阵-java版

剑指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的位置

到这里整个二维数组就走完了!

补充:

  1. :走到遍历过的数也属于越界
  2. :按以上步骤每走过没有越界的位置的数就把它存储到数组中,我这里是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;
    }
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李莲花*

多谢多谢,来自一名大学生的感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值