【題目】函數
給定一個整型矩陣matrix,請按照轉圈的方式打印它。例如:spa
打印結果爲:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11, 103d
要求:額外空間複雜度爲O(1)。code
【分析】blog
用4個變量來標記左上角的點和右下角的點。class
若是要打印這2個點造成矩陣的邊界,能夠寫一個函數,具體是:col1++,加到col2的位置中止,而後row1++,加到row2的位置中止;而後row2--,減到row1停;col2--,減到col1中止變量
打印完最外層的1圈後,左上角的點往右下方移動,右下角的點往左上方移動;當row1>row2或col1>col2時流程結束遍歷
【代碼實現】im
public class PrintMatrixSpiralOrder { public static void spiralOrderPrint(int[][] matrix) { int row1 = 0; int col1 = 0; int row2 = matrix.length - 1; int col2 = matrix[0].length - 1; while (row1 <= row2 && col1 <= col2) { printEdge(matrix, row1++, col1++, row2--, col2--); } } public static void printEdge(int[][] m, int row1, int col1, int row2, int col2) { //若是這個矩陣只有1行數 if (row1 == row2) { //打印這一行 for (int i = col1; i <= col2; i++) { System.out.print(m[i][col1] + " "); } //若是這個矩陣只有1列 } else if (col1 == col2) { //打印這一列 for (int i = row1; i <= row2; i++) { System.out.print(m[i][col1] + " "); } //若是是多乘多的矩陣 } else { int curC = col1; int curR = row1; while (curC != col2) { System.out.print(m[row1][curC] + " "); curC++; } while (curR != row2) { System.out.print(m[curR][col2] + " "); curR++; } while (curC != col1) { System.out.print(m[row2][curC] + " "); curC--; } while (curR != row1) { System.out.print(m[curR][col1] + " "); curR--; } } } public static void main(String[] args) { int[][] matrix = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; spiralOrderPrint(matrix); } }
【題目】總結
給定一個整型正方形矩陣matrix,請把該矩陣調整成順時針旋轉90度的樣子。
要求: 額外空間複雜度爲O(1)。
【分析】
在給定的正方形中,先轉最外圈,再轉裏面的。若是能保證最外層的數能轉對,裏面再依次轉完便可。
舉個例子:
若是能把最外1圈的數轉對,再轉裏面1圈(6,7,10,11),那麼總體就旋轉成功了。
先看最外1圈,從1開始,一、四、1六、13之間相互交換位置,即1→4,4→16,16→13,13→1。
而後從2開始,二、八、1五、9之間交換位置。再看第三組,三、十二、1四、5之間交換位置。
【代碼實現】
public class RotateMatrix { public static void rotate(int[][] matrix) { int row1 = 0; int col1 = 0; int row2 = matrix.length - 1; int col2 = matrix[0].length - 1; while (row1 < row2) { rotateEdge(matrix, row1++, col1++, row2--, col2--); } } /** * 左上角的(row1,col1)和右下角的(row2,col2)必定要組成一個正方形,這是調用此函數的前提 * * @param m * @param row1 左上角的行號 * @param col1 左上角的列號 * @param row2 右下角的行 * @param col2 右下角的列 */ public static void rotateEdge(int[][] m, int row1, int col1, int row2, int col2) { int times = col2 - col1; int tmp = 0; //從1出發,一、四、1六、13之間相互交換位置,直至 for (int i = 0; i < times; i++) { tmp = m[row1][col1 + i]; m[row1][col1 + i] = m[row2 - i][col1]; m[row2 - i][col1] = m[row2][col2 - i]; m[row2][col2 - i] = m[row1 + i][col2]; m[row1 + i][col2] = tmp; } } public static void printMatrix(int[][] matrix) { for (int i = 0; i != matrix.length; i++) { for (int j = 0; j != matrix[0].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); } } public static void main(String[] args) { int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 } }; printMatrix(matrix); rotate(matrix); System.out.println("========="); printMatrix(matrix); } }
【題目】
給定一個矩陣matrix,按照「之」字形的方式打印這個矩陣,例如: 1 2 3 4 5 6 7 8 9 10 11 12
「之」字形打印的結果爲:1,2,5,9,6,3,4,7,10,11,8,12
要求:額外空間複雜度爲O(1)。
【分析】
若是把思路限制在1怎麼變到2,2怎麼變到5,5怎麼變到9。。。這樣是很愚蠢的!
咱們應該這樣想:
有一個(row1,col1),記爲a點、(row2,col2),記爲b點,一開始指向1的位置,並打印它。每次打印完後,a向右移動,移動到最右邊後向下移動;b先向下移動,到最下方後再往右移動。
當a移動到2,b移動到5時,a、b兩點可造成1條對角線;當a移動到3,b移動到9時,兩點間也能夠造成一條對角線;a移動到4,b移動到10時,又是1條對角線。。。
【代碼實現】
public class ZigZagPrintMatrix { public static void printMatrixZigZag(int[][] matrix) { int row1 = 0; int col1 = 0; int row2 = 0; int col2 = 0; int endR = matrix.length - 1; int endC = matrix[0].length - 1; boolean fromUp = false; //當row1沒走到結尾 while (row1 != endR + 1) { printLevel(matrix, row1, col1, row2, col2, fromUp); //到col1觸到最後1列時,row1纔開始增長 row1 = col1 == endC ? row1 + 1 : row1; //若是col1已經到最後,就不變,不然col1增長 col1 = col1 == endC ? col1 : col1 + 1; col2 = row2 == endR ? col2 + 1 : col2; row2 = row2 == endR ? row2 : row2 + 1; //對角線交替着打印 fromUp = !fromUp; } System.out.println(); } /** * (row1,col1)和(row2,col2)兩個點連起來必定是一條對角線,這個函數就是打印對角線上的元素 * 而且這個函數能夠實現從左下方到右上方打印,也能夠實現從右上方到左下方的打印 * @param m * @param row1 * @param col1 * @param row2 * @param col2 * @param fromUp 控制對角線打印的方向。true:右上方到左下方 false:左下方到右上方 */ public static void printLevel(int[][] m, int row1, int col1, int row2, int col2, boolean fromUp) { //fromUp爲true時,從右上方到左下方依次打印對角線上的元素 if (fromUp) { //row1 != row2 + 1等價於row1<=row2 while (row1 != row2 + 1) { System.out.print(m[row1++][col1--] + " "); } //fromUp爲false時,從左下方到右上方依次打印對角線上的元素 } else { while (row2 != row1 - 1) { System.out.print(m[row2--][col2++] + " "); } } } public static void main(String[] args) { int[][] matrix = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; printMatrixZigZag(matrix); } }
【題目】
給定一個有N*M的整型矩陣matrix和一個整數K,matrix的每一行和每一 列都是排好序的。實現一個函數,判斷K是否在matrix中。 例如:
若是K爲7,返回true;若是K爲6,返回false。
要求:時間複雜度爲O(N+M),額外空間複雜度爲O(1)。
【分析】
若是經過遍歷的方式,一共N*M個數,每一個數都遍歷,時間複雜度就是O(N*M),顯然不符合要求。
經過例子來分析這個題目:
若是要判斷6是否在上面的矩陣中,能夠從右上角9開始查,9>6,由於每一列都是有序的,因此9這列底下的數必定沒有6;
而後從9向左移動,來到7的位置,7>6,因此7底下的數必定沒有6
繼續從7往左移動,來到5的位置,5<6,因此5的左邊必定比6小,因而從5往下走,來到6的位置,返回true
總結就是:從右上角開始,當前數大於要找的數,向左移動;當前數小於要找的數,向下移動;當前數若是等於要找的數,返回true;若是走到越界的位置還沒找到,必定不存在,返回false。
注意:從左下角開始找也是能夠的。可是不能從左上角或右下角開始找!
【代碼實現】
public class FindNumInSortedMatrix { public static boolean isContains(int[][] matrix, int K) { int row = 0; int col = matrix[0].length - 1; while (row < matrix.length && col > -1) { if (matrix[row][col] == K) { return true; } else if (matrix[row][col] > K) { col--; } else { row++; } } return false; } public static void main(String[] args) { int[][] matrix = new int[][]{{0, 1, 2, 3, 4, 5, 6},// 0 {10, 12, 13, 15, 16, 17, 18},// 1 {23, 24, 25, 26, 27, 28, 29},// 2 {44, 45, 46, 47, 48, 49, 50},// 3 {65, 66, 67, 68, 69, 70, 71},// 4 {96, 97, 98, 99, 100, 111, 122},// 5 {166, 176, 186, 187, 190, 195, 200},// 6 {233, 243, 321, 341, 356, 370, 380} // 7 }; int K = 233; System.out.println(isContains(matrix, K)); } }