剑指offer-29-顺时针打印矩阵

题目:

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:

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。
思路:
在这里插入图片描述
思路
  每次打印矩阵最外面的一圈(用方法printMatrixInCircle()表示),每次都是这个操作,所以可以采用递归。每次打印矩阵的左上角的横纵坐标相同,即为start,而其余三个角的坐标都与行列数以及start有关,因此只需要for循环即可实现打印。

package offer;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author kankan
 * @creater 2019-06-30 20:42
 */
//题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

public class PrintMatrix {
    public ArrayList<Integer> printMatrix(int[][] matrix) {
        if (matrix == null || matrix.length <= 0)
            return null;
        ArrayList<Integer> result = new ArrayList<>();
        printMatrixInCircle(matrix, 0, result);
        return result;
    }

    private void printMatrixInCircle(int[][] matrix, int start, ArrayList<Integer> result) {
        int row = matrix.length;//行
        int col = matrix[0].length;//列
        int endCol = col - 1 - start;//列的最大索引
        int endRow = row - 1 - start;//行的最大索引
        if (endCol < start || endRow < start)
            return;
        //仅一行
        if (endRow == start) {
            for (int i = start; i <= endCol; i++) {
                System.out.print(matrix[start][i] + " ");
                result.add(matrix[start][i]);
            }
            return;  //记得结束
        }
        //仅一列
        if (endCol == start) {
            for (int i = start; i <= endRow; i++) {
                System.out.print(matrix[i][start] + " ");
                result.add(matrix[i][start]);
            }
            return;  //记得结束
        }

        //打印边界
        //从左到右
        for (int i = start; i <= endCol; i++) {
            System.out.print(matrix[start][i] + " ");
            result.add(matrix[start][i]);
        }
        //从上到下
        for (int i = start + 1; i <= endRow; i++) {
            System.out.print(matrix[i][endCol] + " ");
            result.add(matrix[i][endCol]);
        }
        //从右到左
        for (int i = endCol - 1; i >= start; i--) {
            System.out.print(matrix[endRow][i] + " ");
            result.add(matrix[endRow][i]);
        }
        //从下到上
        for (int i = endRow - 1; i >= start + 1; i--) {
            System.out.print(matrix[i][start] + " ");
            result.add(matrix[i][start]);
        }

        //继续打印更内部的矩阵,令start+1
        printMatrixInCircle(matrix, start + 1, result);
    }


    public static void main(String[] args) {
        PrintMatrix demo = new PrintMatrix();
        int[][] a = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
//      int[][] a= {};
//      int[][] a= {{}};
//      int[][] a= {{1}};
//      int[][] a= {{1,2,3,4}};
//      int[][] a= {{1},{2},{3},{4}};
//      int[][] a= {{1,2,3},{4,5,6}};
//      int[][] a=null;
        ArrayList<Integer> result = new ArrayList<>();
        result = demo.printMatrix(a);
        System.out.println(result);
    }
}

在这里插入图片描述
剑指offer中提供的思路其实要更容易一些,首先分析循环结束的条件,打印第一圈左上角坐标为(0,0),第二圈左上角坐标为(1,1),以此类推每次循环的行列起始坐标都是相同的(start,start)。因此可以分析出循环继续的条件是columns > startX2并且rows > startY2。有了循环继续的条件后,我们要分析每次循环那4步的前提条件。第一步肯定是必定会经过的,因为打印一圈至少有一步。第二步的前提是终止行号大于起始行号,第三步的前提是终止行号大于起始行号,终止列号大于起始列号,因为圈内至少有2行2列,第四步的前提条件是终止行号比起始行号至少大2,终止列号大于起始行号,即至少有3行2列。代码如下:

package offer;

import java.util.ArrayList;

/**
 * @author kankan
 * @creater 2019-07-01 21:26
 */
public class PrintMatrix2 {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> result = new ArrayList<>();
        if (0 == matrix.length){
            return result;
        }
        int rows = matrix.length;//行数
        int columns = matrix[0].length;//列数
        //循环继续的条件是columns > startX*2并且rows > startY*2
        int start = 0;
        while (rows > start * 2 && columns > start * 2){
            printOneCircle(matrix,start,result);
            start++;
        }
        return result;
    }

    private void printOneCircle(int[][] matrix, int start, ArrayList<Integer> result) {
        int endCol = matrix[0].length - 1 - start;//列
        int endRow = matrix.length - 1 - start;//行
        //从左往右
        //第一步,已经判断打印数组不为null,说明至少有一行
        for (int i = start; i <= endCol; i++) {
            System.out.print(matrix[start][i] + " ");
            result.add(matrix[start][i]);
        }
        //从上往下
        //第二步:终止行号大于起始行号
        if (start < endRow){
            for (int i = start + 1; i <= endRow; i++) {
                System.out.print(matrix[i][endCol] + " ");
                result.add(matrix[i][endCol]);
            }
        }
        //从右往左(判断是否会重复打印)
        //第三步:终止行号大于起始行号之外,要求终止列号大于起始列号之外
        if (start < endCol && start < endRow){
            for (int i = endCol - 1; i >= start; i--) {
                System.out.print(matrix[endRow][i] + " ");
                result.add(matrix[endRow][i]);
            }
        }
        // 从下往上(判断是否会重复打印)
        //第四步:终止行号比起始行号至少大于2,终止列号大于起始列号之外
        if (start < endCol && start < endRow - 1){
            for (int i = endRow - 1; i >= start + 1; i--) {
                System.out.print(matrix[i][start] + " ");
                result.add(matrix[i][start]);
            }
        }
    }
    public static void main(String[] args) {
        PrintMatrix demo = new PrintMatrix();
        int[][] a = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
//      int[][] a= {};
//      int[][] a= {{}};
//      int[][] a= {{1}};
//      int[][] a= {{1,2,3,4}};
//      int[][] a= {{1},{2},{3},{4}};
        //int[][] a= {{1,2,3},{4,5,6}};
//      int[][] a=null;
        ArrayList<Integer> result = new ArrayList<>();
        result = demo.printMatrix(a);
        System.out.println(result);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值