[剑指Offer]顺时针打印矩阵

面试题20:顺时针打印矩阵

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

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

解题思路

对一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2,2)。我们发现5>2*2。对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标依然为(2,2)。我们发现6>2*2依然成立。于是我们可以得出,让循环继续的条件是columns > startX * 2并且rows > startY * 2。所以我们可以用如下的循环来打印矩阵:

public void printMatrix(int [][] matrix) {
        int columns = matrix.length;
        int rows = matrix[0].length;
         if(matrix == null || columns <= 0 || rows <= 0)
             return;
         int start = 0;
         while (columns > start * 2 && rows > start * 2) {
            printMatrixInCircle(matrix,columns,rows,start);
            start++;
        }
    }

接着我们可以把打印一圈分为四步,第一步从左到右打印一行,第二步从上到下打印一列,第三步从右到左打印一行,第四步从下到上打印一列。每一步根据起始坐标和终止坐标用一个循环就能打印出一行或者一列。

第一步总是有必要的,因为打印一圈至少有一步。如果只有一行,那么就不用第二步了。也就是需要第二步的前提是终止行号大于起始行号。需要第三步打印的前提条件是圈内至少有两行两列,也就是说除了要求终止行号大于起始行号之外,还要求终止列号大于起始列号。同理,打印第四步的前提条件是至少有三行两列,因此要求终止行号比起始行号至少大2,同时终止列号大于起始行号。

完整代码:

package 顺时针打印矩阵;

public class Solution {

    public void printMatrix(int [][] matrix) {
        int columns = matrix.length;
        int rows = matrix[0].length;
         if(matrix == null || columns <= 0 || rows <= 0)
             return;
         int start = 0;
         while (columns > start * 2 && rows > start * 2) {
            printMatrixInCircle(matrix,columns,rows,start);
            start++;
        }
    }

    private void printMatrixInCircle(int[][] matrix, int columns, int rows, int start) {
        int endX = columns - 1 - start;
        int endY = rows - 1 - start;

        //从左到右打印一行
        for (int i = 0; i <= endX; i++) {
            int number = matrix[start][i];
            printNumber(number);
        }
        //从上到下打印一列
        if(start < endY){
            for (int i = start+1; i < endY; i++) {
                int number = matrix[i][endX];
                printNumber(number);
            }
        }

        //从右到左打印一行
        if(start < endX && start < endY){
            for (int i = endX - 1; i >= start; i--) {
                int number = matrix[endX][i];
                printNumber(number);
            }
        }

        //从下到上打印一行
        if(start < endX && start < endY-1){
            for (int i = endY-1; i >= start + 1; i--) {
                int number = matrix[i][start];
                printNumber(number);
            }
        }
    }

    private void printNumber(int number) {
        System.out.println(number + "");
    }


}

你可能感兴趣的:(剑指offer)