顺时针打印矩阵

1.本题知识点
   矩阵
2. 题目描述
   输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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。
3. 思路
   ① 把矩阵看成由若干个顺时针方向的圈组成。先打印外面的圈,再打印里面的圈。

在这里插入图片描述

   ② 循环打印的条件:rows > startX * 2 且 cols > startY * 2。 rows为矩阵行数,cols为矩阵列数。startX为起始点X坐标,startY为起始点Y坐标。
   ③ 打印一个圈如何实现?如图,分为四部分:从左到右打印,从上到下打印,从右到左打印,从下到上打印。

在这里插入图片描述

   ④ 单圈打印的特殊情况。一个圈可能只有三步、两步、一步。所以要考虑到。

在这里插入图片描述

   分析特殊情况:第一步肯定需要,因为打印一个圈至少需要一步;第二步执行的前提条件就是终止行号需大于起始行号;第三步执行的前提条件是至少有2行2列;第四部执行的前提条件是至少有3行2列。
   ⑤ 总结:需要2个方法,多个圈循环的控制方法和 单个圈打印的方法,并考虑特殊情况。
   Java 循环版:
import java.util.ArrayList;
public class Solution {
    //结果保存
    private ArrayList<Integer> result = new ArrayList<>();
    
    //循环控制方法
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       if(matrix == null) return null;
        int rows = matrix.length;
        int cols = matrix[0].length;
        int start  = 0;//起始点
        
        while(rows > start * 2 && cols > start * 2){
            printSingleCircle(matrix, rows, cols, start);//打印外面的圈
            ++start;//继续打印里面的圈
        }
        
        return result;
    }
    
    //单圈打印方法
    void printSingleCircle(int [][] matrix,int rows, int cols, int start){
        int endCol = cols - 1 - start;//终止列号
        int endRow = rows - 1 - start;//终止行号
        
        //第一步从左到右
        for(int i = start ; i <= endCol; ++i){
            result.add(matrix[start][i]);
        }
        
        //第二步从上到下:保证终止行号 大于 起始行号
        if(endRow > start)
        {
            //此循环逻辑参照图理解
            for(int i = start + 1 ; i <= endRow; ++i){
                result.add(matrix[i][endCol]);
            }
        }
        
        //第三步从右到左:保证至少2行2列
        if(start < endCol && start < endRow )
        {
            //此循环逻辑参照图理解
            for(int i = endCol - 1; i >= start; --i){
                result.add(matrix[endRow][i]);
            }
        }
        
        //第四步从下到上:保证至少3行2列
        if(start < endCol && start < endRow - 1 )
        {
            //此循环逻辑参照图理解
            //第四步遍历值时的边界最多,应该说从第二步开始遍历都要仔细考虑边界。
            //因为第一步占据了整个第一行,第二步只能从第2行开始遍历,所以int i = start + 1 
            //同理,需要考虑:第二步第一步占据了第一行和最后一列,第三步二步一步占据了第一行、最后一列和最后一行。
            for(int i = endRow - 1; i >= start+1; --i){
                result.add(matrix[i][start]);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值