题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每个数字。例如:若是输入以下矩阵:spa
1,2,3,4class
5,6,7,8test
9,10,11,12循环
13,14,15,16im
则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.static
当遇到一个复杂的问题的时候,咱们能够用图形来帮助咱们来思考。因为是从外圈到内圈的顺序依次打印,咱们能够把矩阵想象成若干个圈,如图所示。咱们可疑用一个循环来打印矩阵,每一次打印矩阵中的一个圈。img
接下来分析循环结束的条件。假设这个矩阵的行数是rows,列数是 columns。打印第一个圈是左上角元素的坐标是(0,0),第二圈的左上角的坐标是(1,1),以此类推。咱们注意到,左上角的坐标中行标和列标老是 相同的,因而可疑在矩阵中选取左上角为(start,start)的一圈为咱们分析的目标。思考
对一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为 (2,2)。咱们发现5>2*2.对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然为(2,2)。咱们发现6>2*2依然 成立。因而咱们能够得出继续循环的条件是columns>startX*2而且rows>startY*2.while
接着咱们考虑如何打印一圈的功能,即如何实现 PrintMatrixInCircle。如图所示,咱们能够把打印一圈分为四步:第一步从作到右打印一行,第二步从上到下打印一行,第三步从右到左打印 一行,第四步从下到上打印一列。每一步咱们根据起始坐标用一个循环就能打印出一行或者一列。co
不过值得注意的是,最后一圈有可能退化成只有一行、只有一列,甚至只有一个数字,所以打印这样的一圈就再也不须要四步。图是几个退化的例子,打印一圈分别只须要三步、两步甚至只有一步。
所以咱们要仔细分析打印时的每一步的前提条件。第一步老是须要的,因 为打印一圈至少须要一步。若是只有一行,那么就不用第二步了。也就是须要第二步的前提条件是终止号大于起止号。须要第三步打印的前提条件是圈内至少有两行 两列,也就是说除了要求终止行号大于起始行号以外,还要求终止列号大于起始列号。同理,须要打印第四步的前提条件是至少有三行两列,所以要求终止行号比其 实行号至少大2,同时终止列号大于起始列号。
package cglib;
public class DeleteNode {
public void printMatrixInCircle(int[][] array){
if(array == null)
return;
int start = 0; //3*4
System.out.println("array[0].length="+array[0].length);
System.out.println("array.length="+array.length);
while(array[0].length > start*2 && array.length >start*2){
printOneCircle(array,start);
start++;
}
}
//1,2,3,4
//5,6,7,8
//9,10,11,12
private void printOneCircle(int[][] array,int start){
int columns = array[0].length; //列数
int rows = array.length; //行数
int endX = columns - 1 - start; //3
int endY = rows - 1 - start; //2
//从左到右打印一行
for(int i = start;i <= endX ;i++){
int number = array[start][i]; //1,2,3,4
System.out.print(number+",");
}
//从上到下打印一列
if(start <endY){
for(int i = start +1;i<=endY;i++){ //8,12
int number = array[i][endX]; //列固定
System.out.print(number+",");
}
}
//从右到左打印一行
if(start < endX && start < endY){ //11,10,9
for(int i = endX -1;i>=start;i--){
int number = array[endY][i];
System.out.print(number+",");
}
}
//从下到上打印一列
if(start <endY && start <endY -1){
for(int i =endY -1;i>=start+1;i--){
int number = array[i][start];
System.out.print(number+",");
}
}
}
public static void main(String[]args){
int[][] arr={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
DeleteNode test = new DeleteNode();
test.printMatrixInCircle(arr);
}
输出
array[0].length=4
array.length=3
1,2,3,4,8,12,11,10,9,5,6,7,
或者:
第一步打印一行时,全部的数字的行号是固定的(startY),不一样数字的列号不一样。咱们须要传入一个起始列号(startX)和终止列号(endX)。第二步打印一列时,全部的数字的列号是固定的,不一样的数字的行号不一样。咱们须要传入一个起始行号(startY + 1)和一个终止行号(endY)。第三步和第四步和前面两步相似,读者能够本身分析。
接下来咱们须要考虑特殊状况。并非全部数字圈都须要四步来打印。好比当一圈退化成一行的时候,也就是startY等于endY的时候,咱们只须要第一步就把全部的数字都打印完了,其他的步骤都是多余的。所以咱们须要考虑第2、3、四步打印的条件。根据前面咱们分析,不难发现打印第二步的条件是startY < endY。对于第三步而言,若是startX等于endX,也就是这一圈中只有一列数字,那么全部的数字都在第二步打印完了;若是startY等于endY,也就是这一圈中只有一行数字,那么全部的数字都在第一步打印完了。所以须要打印第三步的条件是startX < endX && startX < endY。第四步最复杂,首先startX要小于endX,否则全部的数字都在一列,在第二步中就都打印完了。另外,这个圈中至少要有三行数字。若是只有一行数字,全部数字在第一步中打印完了;若是只有两行数字,全部数字在第一步和第三步也都打印完了。所以打印第四步须要的条件是startY < endY – 1。
package cglib;
public class DeleteNode {
public void printCircle(int[][] matrix, int startX, int startY, int endX, int endY) {
// 最后只剩一列
if (startY == endY) {
for (int i = startX; i <= endX; i++ ) {
System.out.println("最后只剩一列 :"+matrix[i][endY]);
}
return;
}
// 最后只剩一行
if (startX == endX) {
for (int i = startY; i <= endY; i++ ) {
System.out.println("最后只剩一行:"+matrix[startX][i]);
}
return;
}
for (int i = startY; i < endY; i++ ) { //从左到右,行数固定
System.out.println("从左到右:"+matrix[startX][i]);
}
for (int i = startX; i < endX; i++ ) { //从上到下,列数固定
System.out.println("从上到下:"+matrix[i][endY]);
}
for (int i = endY; i > startY; i-- ) { //从右到左,行数固定
System.out.println("从右到左:"+matrix[endX][i]);
}
for (int i = endX; i > startX; i-- ) { // 从下到上,列数固定
System.out.println("从下到上:"+matrix[i][startY]);
}
}
public void printMatrix(int[][] matrix) {
if (matrix == null) {
return;
}
int startX = 0;
int startY = 0;
int endY = matrix[0].length - 1; //列
int endX = matrix.length - 1; //行
while ((startX <= endX) && (startY <= endY)) {
printCircle(matrix, startX, startY, endX, endY);
startX++;
startY++;
endX--;
endY--;
}
}
public static void main(String[]args){
int[][] arr={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
DeleteNode test = new DeleteNode();
test.printMatrix(arr);
}
}
输出:
从左到右:1 从左到右:2 从左到右:3 从上到下:4 从上到下:8 从右到左:12 从右到左:11 从右到左:10 从下到上:9 从下到上:5 最后只剩一行:6 最后只剩一行:7