剑指offer JZ29 顺时针打印矩阵

描述

剑指offer JZ29 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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]
数据范围:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100

方法一:设置方向的优先级,并且单独考虑特殊情况进行遍历

思路:由于需要顺时针遍历矩阵,我们可以直观想到方向的优先级:右、下、左、上。我们可以通过标记已经遍历过的数字,每次都按顺序判断这四个方位,在前一个行不通时才会走下一个,大体实现顺时针遍历。但是存在一种特殊情况,就是在需要向上遍历的时候,由于是需要先判断右方向,所以遍历方向会向右走而不向上,这个时候我们可以在判断四个方向之前再加入一个条件:即在右方和上方都可通行的时候,优先向上走,即可解决。
代码实现:

import java.util.*;
import java.util.ArrayList;
public class Solution {
    //标记位置是否已遍历
    boolean[][] flags;
    
    // 此方法用于根据优先级选择方向
	 public ArrayList<Integer> printMatrix(int [][] matrix) {
	 ArrayList<Integer> list = new ArrayList<>();
	 //先判断特殊情况
       if (matrix.length==0 || matrix[0].length==0) return list;
       //初始化标记数组
       flags = new boolean[matrix.length][matrix[0].length];
       int x = 0;
       int y = 0;
       
       //循环遍历
       while(true) {
        flags[x][y] = true;
        list.add(matrix[x][y]);
        //如果上方和右方同时可通行,优先往上走
        if (checkAuth(x, y+1) && checkAuth(x-1, y)) x--;
        //右方能通行
        else if (checkAuth(x, y+1)) y++;
        //下方能通行
        else if (checkAuth(x+1, y)) x++;
        //左方能通行
        else if (checkAuth(x, y-1)) y--;
        //上方能通行
        else if (checkAuth(x-1, y)) x--; 
        //无路可走,返回集合
        else return list;
       }
    }
    //通过数字的坐标判断此点能不能通行
    public boolean checkAuth(int x, int y) {
        if (x < 0 || x > flags.length-1 || y < 0 || y > flags[0].length-1 || flags[x][y]) return false;
        return true;
    }
}

方法二:设置边界条件,经过遍历循环实现

思路:设置上下左右四种边界,每进行一次遍历,就将对应的边界改变,当边界冲突的时候退出循环

public class Solution {
   public ArrayList<Integer> printMatrix(int [][] matrix) {
       ArrayList<Integer> list = new ArrayList<>();
       if (matrix.length==0 || matrix[0].length==0) return list;
       //初始化四条边界。
       int top = 0;
       int left = 0;
       int bottom = matrix.length-1;
       int right = matrix[0].length-1;
       //边界条件冲突时,退出循环
       while (top <=  bottom && left <= right) {
       //第一次循环,从左到右
           for (int i = left; i <= right; i++) list.add(matrix[top][i]);
           top++;
           //上边界在下边界之下,遍历结束,退出循环
           if (top > bottom) break;
           //后面的也是一样的道理,分别时从上往下,从左往右,从下往上,并且每一次都需要判断遍历是否结束。
           for (int i = top; i <= bottom; i++) list.add(matrix[i][right]);
           right--;
           if (left > right) break;
           for (int i = right; i >= left; i--) list.add(matrix[bottom][i]);
           bottom--;
           if (top > bottom) break;
           for (int i = bottom; i >= top; i--) list.add(matrix[i][left]);
           left++;
           if (left > right) break;
       }
       return list;
   }
}
  • 24
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值