题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下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.
分析
从外圈到内圈的顺序依次打印的。
假设这个矩形的行数是rows,列数是columns。打印第一圈的左上角坐标为(0, 0),第二圈左上角的坐标为(1, 1),可以发现左上角坐标中行标和列标总是相同的。所以可以在矩形上选取左上角(start, start)的一圈为分析对象。
对于一个5x5的矩阵,最后一圈只有一个数字,对应的坐标是(2, 2)。发现5>2x2。对于一个6x6的矩阵,最后一圈有4个数字,其左上角的坐标仍然是(2, 2),发现6>2x2仍然成立,所以让循环的条件为columns > startX * 2并且rows > startY * 2。
下来分析如何打印一圈
将打印一圈分为4步:
- 第一步,从左到右打印一行
- 第二步,从上到下打印一列
- 第三步,从右到左打印一行
- 第四步,从下到上打印一列
每一步根据起始坐标和终止坐标来用一个循环即能实现。
分析打印时每一步的前提条件:
- 第一步是必须的,因为打印一圈至少有一步。
- 如果只有一行,那么就不需要第二步了,也就是说第二步的前提条件是终止行号大于起始行号
- 需要第三步的前提条件是圈内至少有两行两列,也就是说除了终止行号大于起始行号,还要求终止列号大于起始列号。
- 第四步的前提条件是至少有三行两列,因此要求终止行号比起始行号至少大2,同时终止列好=号大于起始列号。
代码实现
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] matrix) {
if(matrix == null || matrix.length <= 0 || matrix[0].length <= 0) {
return null;
}
int start = 0;
int columns = matrix[0].length;
int rows = matrix.length;
ArrayList list = new ArrayList<Integer>();
while((columns > start * 2) && (rows > start * 2)) {
this.AppendListMatrix(list, matrix, columns, rows, start);
++start;
}
return list;
}
public void AppendListMatrix(ArrayList list, int[][] matrix, int columns, int rows, int start) {
int endX = columns - 1 - start;
int endY = rows - 1 - start;
for (int i = start; i <= endX; i++) {
list.add(matrix[start][i]);
}
if(start < endY) {
for (int i = start + 1; i <= endY; i++) {
list.add(matrix[i][endX]);
}
}
if(start < endX && start < endY) {
for (int i = endX - 1; i >= start ; i--) {
list.add(matrix[endY][i]);
}
}
if(start < endX && start < endY - 1) {
for (int i = endY - 1; i >= start +1; i--) {
list.add(matrix[i][start]);
}
}
}
}