<剑指offer> 第17题
题目:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
思路:
把打印一圈分为四步:第一步从左往右打印一行,第二步从上到下打印一行,第三步从右向左打印一行,第四步从下到上打印一行,每一步根据起始坐标和终止坐标用一个循环就能打印出一行或者一列。
最后一圈有可能退化成只有一行、只有一列、甚至只有一个数字,因为打印这样的一圈就不再需要四步。
分析一下打印时每一步的前提条件。第一步总是必需的,打印一圈至少有一步。如果只有一行,那么就不用第二步了。
打印第二步的前提条件是 终止行号>起始行号
打印第三步的前提条件是 终止行号>起始行号 && 终止列号>起始列号
打印第四步的终止条件是 终止行号比起始行号至少大2,同时终止列号>起始列号
代码:
public class Seventeenth { public static void printMatrix(int[][] numbers){ if(numbers == null){ return; } //记录开始的行 int x = 0; //记录开始的列 int y = 0; //行号最大是 (numbers.length - 1)/2 //列号最大是 (numbers[0].length -1)/2 while(x * 2 < numbers.length && y * 2 < numbers[0].length){ printMatrixInCircle(numbers, x, y); x ++; y ++; } } public static void printMatrixInCircle(int[][] numbers, int x, int y){ int rows = numbers.length; int cols = numbers[0].length; //输出最上面一行 for(int i = y; i <= cols - y - 1; i ++){ System.out.println(numbers[x][i] + " "); } //输出最右边一列则环高度至少为2 //rows - x -1 表示环最下边的那一行的行号 if(rows - x - 1> x){ for(int i = x + 1; i <= rows - x - 1; i ++){ System.out.println(numbers[i][cols - y -1] + " "); } } //环的高度至少为2并且环的宽度至少是2才会输出下面那一行 //cols - 1 - y 表示环最右边的那一列的列号 if (rows - x - 1 > x && cols - 1 - y > y){ for(int i = cols - y - 2; i >= y; i --){ System.out.println(numbers[rows - 1 - x][i] + " "); } } //环的宽度至少是2并且环的高度至少为3才会输出最左边那一列 //rows - x - 1 表示环最下的那一行的行号 if(cols - 1 - y > y && rows - 1 - x > x + 1){ //左边那一列的第一个和最后一个已经被输出 for(int i = rows - 1 - x - 1 ; i >= x + 1; i --){ System.out.println(numbers[i][y] + " "); } } } public static void main(String[] args){ int[][] arr = { {1,2,3}, {4,5,6}, {7,8,9} }; printMatrix(arr); } }