題目:輸入一個矩陣,按照從外向裏以順時針的順序依次打印出每個數字。例如:若是輸入以下矩陣: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