矩阵【基础算法题】
题目一
思路:
①得到二维数组左上角(a,b)和右下角(c,d)的点,就能打印出最外层的框。
如果,得到的左上角(a,b)和右下角(c,d)是在同一行,即a=c,说明该数组是棒状结构,直接从(a,b)加到(a,d)即可。
如果,得到的左上角(a,b)和右下角(c,d)是在同一列,即b=d,说明该数组是棒状结构,直接从(a,b)加到(c,b)即可。
②最外层框打完之后,左下角和右下角的点,同时往对角线方向走一个点,再打印里面一层的框,···以此类推,直到左下角的行或列大于右下角的行或列就可以停了。
代码实现
1 package class_03; 2 3 public class Code_06_PrintMatrixSpiralOrder { 4 5 public static void spiralOrderPrint(int[][] matrix) { 6 int tR = 0;//左下角的行 7 int tC = 0;//左下角的列 8 int dR = matrix.length - 1;//右下角的行 9 int dC = matrix[0].length - 1;//右下角的列 10 while (tR <= dR && tC <= dC) {//左下角没有越过右下角,就说明还有数可以打印 11 printEdge(matrix, tR++, tC++, dR--, dC--); 12 } 13 } 14 15 public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) { 16 if (tR == dR) {//左下角和右下角在同一行 17 for (int i = tC; i <= dC; i++) { 18 System.out.print(m[tR][i] + " "); 19 } 20 } else if (tC == dC) {//左下角和右下角在同一列 21 for (int i = tR; i <= dR; i++) { 22 System.out.print(m[i][tC] + " "); 23 } 24 } else { 25 int curC = tC; 26 int curR = tR; 27 while (curC != dC) { 28 System.out.print(m[tR][curC] + " "); 29 curC++; 30 } 31 while (curR != dR) { 32 System.out.print(m[curR][dC] + " "); 33 curR++; 34 } 35 while (curC != tC) { 36 System.out.print(m[dR][curC] + " "); 37 curC--; 38 } 39 while (curR != tR) { 40 System.out.print(m[curR][tC] + " "); 41 curR--; 42 } 43 } 44 } 45 46 public static void main(String[] args) { 47 int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 48 { 13, 14, 15, 16 } }; 49 spiralOrderPrint(matrix); 50 51 } 52 53 }
题目二
思路
同样,得到矩阵的左上角和右下角,先转外圈的,再转内圈的,···以此类推,直到把框转没,最终就全部转了90度了。
外层为例:
首先1、4、16、13,这四个点先交换位置,1→4、4→16、16→13、13→1;
接着2、8、15、9,这四个点交换位置,2→8、8→15、15→9、9→2;
接着3、12、14、5,这四个点交换位置,3→12、12→14、14→5、5→3;
····内层以此类推
代码实现
1 package class_03; 2 3 public class Code_05_RotateMatrix { 4 5 public static void rotate(int[][] matrix) { 6 int tR = 0; 7 int tC = 0; 8 int dR = matrix.length - 1; 9 int dC = matrix[0].length - 1; 10 while (tR < dR) { 11 rotateEdge(matrix, tR++, tC++, dR--, dC--); 12 } 13 } 14 15 public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) { 16 int times = dC - tC; 17 int tmp = 0; 18 for (int i = 0; i != times; i++) { 19 tmp = m[tR][tC + i]; 20 m[tR][tC + i] = m[dR - i][tC]; 21 m[dR - i][tC] = m[dR][dC - i]; 22 m[dR][dC - i] = m[tR + i][dC]; 23 m[tR + i][dC] = tmp; 24 } 25 } 26 27 public static void printMatrix(int[][] matrix) { 28 for (int i = 0; i != matrix.length; i++) { 29 for (int j = 0; j != matrix[0].length; j++) { 30 System.out.print(matrix[i][j] + " "); 31 } 32 System.out.println(); 33 } 34 } 35 36 public static void main(String[] args) { 37 int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, 38 { 13, 14, 15, 16 } }; 39 printMatrix(matrix); 40 rotate(matrix); 41 System.out.println("========="); 42 printMatrix(matrix); 43 44 } 45 46 }
题目三
思路
设置A、B两个点,一开始都在(0,0)位置。每次A跟B都同时各自走一步
A总是向右移动,撞到最右了,往下移动;
B总是向下移动,撞到最右了,往右移动;
最终题目就转换为,已知一条对角线的右上点和左下点 ,怎么打印这条对角线?解决了这个问题,就可以依次打印每条对角线,首先打印第一个点(0,0),然后开始打印对角线上的数,第一条从右上往左下打印,第二条从左下往右上打印,(可以设置一个布尔值来记录打印的方向是左上还是右下)···以此类推,直到打印完最后一条对角线上的数,最后打印整个矩阵右下角的数,就实现了题目的要求。
代码实现
1 package class_03; 2 3 public class Code_08_ZigZagPrintMatrix { 4 5 public static void printMatrixZigZag(int[][] matrix) { 6 int tR = 0; 7 int tC = 0; 8 int dR = 0; 9 int dC = 0; 10 int endR = matrix.length - 1; 11 int endC = matrix[0].length - 1; 12 boolean fromUp = false; 13 while (tR != endR + 1) { 14 printLevel(matrix, tR, tC, dR, dC, fromUp); 15 tR = tC == endC ? tR + 1 : tR; 16 tC = tC == endC ? tC : tC + 1; 17 dC = dR == endR ? dC + 1 : dC; 18 dR = dR == endR ? dR : dR + 1; 19 fromUp = !fromUp; 20 } 21 System.out.println(); 22 } 23 24 public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, 25 boolean f) { 26 if (f) { 27 while (tR != dR + 1) { 28 System.out.print(m[tR++][tC--] + " "); 29 } 30 } else { 31 while (dR != tR - 1) { 32 System.out.print(m[dR--][dC++] + " "); 33 } 34 } 35 } 36 37 public static void main(String[] args) { 38 int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; 39 printMatrixZigZag(matrix); 40 41 } 42 43 }
题目四
思路
从右上角开始找,如果当前位置上的数比要找的数大,就往左走,如果当前位置上的数比要找的数小,就往下走,···以此类推,直到找到返回true,如果走到左下角还是没有就返回false。
复杂度O(n+m)
总结
题目给出的数据状况很特殊或问法特殊的话,就从这个特殊的数据状况上或问法上来着手,往往能够找到最优解。
代码实现
1 package class_03; 2 3 public class Code_09_FindNumInSortedMatrix { 4 5 public static boolean isContains(int[][] matrix, int K) { 6 int row = 0; 7 int col = matrix[0].length - 1; 8 while (row < matrix.length && col > -1) { 9 if (matrix[row][col] == K) { 10 return true; 11 } else if (matrix[row][col] > K) { 12 col--; 13 } else { 14 row++; 15 } 16 } 17 return false; 18 } 19 20 public static void main(String[] args) { 21 int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0 22 { 10, 12, 13, 15, 16, 17, 18 },// 1 23 { 23, 24, 25, 26, 27, 28, 29 },// 2 24 { 44, 45, 46, 47, 48, 49, 50 },// 3 25 { 65, 66, 67, 68, 69, 70, 71 },// 4 26 { 96, 97, 98, 99, 100, 111, 122 },// 5 27 { 166, 176, 186, 187, 190, 195, 200 },// 6 28 { 233, 243, 321, 341, 356, 370, 380 } // 7 29 }; 30 int K = 233; 31 System.out.println(isContains(matrix, K)); 32 } 33 34 }