矩阵回型遍历

矩阵回型遍历


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 画图

简单来说就是需要将一个矩阵以回字形打印出来,我们来把图画一下:

  1. 正常情况:

    在这里插入图片描述

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

在这里插入图片描述

  1. 只有一列的情况:

    在这里插入图片描述

当然了还有一种情况属于2.与3.重叠的情况,即只有一个元素,这里就不罗嗦了。

1.2 遍历的方式

既然是矩阵就得遍历对吧?那么我们可以采用什么样的方式来遍历呢?

  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. 总结

  1. 先画图寻找可能的遍历方法…
  2. 确定好有效的遍历方法
  3. 确定遍历结束条件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值