数组和矩阵问题:转圈打印矩阵

题目

     给定一个整型矩阵 matrix, 请按照转圈的方式打印它。

  例如:

  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

要求

  额外空间复杂度为 O(1)。

难度

  一星

解答

  本题在算法上没有什么难度,关键在于设计一种逻辑容易理解、代码易于实现的转圈遍历方式。这里介绍这样一种矩阵处理方式,该方式不仅可用于此题,还适合很多其他的面试题,就是矩阵分圈处理。在矩阵中用左上角的坐标 (tR, tC) 和右下角的坐标 (dR, dC) 就可以表示一个子矩阵,比如,题目中的矩阵,当 (tR, tC) = (0, 0)、(dR, dC) = (3,3) 时,表示子矩阵就是整个矩阵,那么这个子矩阵最外层的部分如下:

  1   2   3  4

  5            8

  9                 12

  13     14     15    16

  如果能把这个矩阵的外层转圈打印出来,那么在(tR, tC) = (0,0)、(dR, dC) = (3,3) 时,打印的结果为:1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5。接下来令 tR 和 tC 加 1,即 (tR, tC) = (1,1), 令 dR 和 dC 减 1, 即 (dR, dC) = (2,2), 此时表示的子矩阵如下:

       6    7

  10  11

  再把这个子矩阵转圈打印出来,结果为:6, 7, 11, 10。再令 tR 和 tC 加 1,即(tR, tC) = (2,2), 令 dR 和 dC 减 1, 即 (dR, dC) = (1,1)。如果发现左上角坐标跑到了右下角坐标的右方或者下方,整个过程就停止了。已经打印的所有结果连起来就是我们要求的打印结果。具体请参看如下代码中的 spiralOrderPrint 方法, 其中 printEdge 方法是转圈打印一个子矩阵的外层。

 1 public class Main {
 2     
 3     public static void main(String[] args) {
 4         int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
 5         //1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 
 6         new Main().spiralOrderPrint(matrix);
 7     }
 8     
 9     //打印矩阵
10     public void spiralOrderPrint(int[][] matrix) {
11         int tR = 0;
12         int tC = 0;
13         int dR = matrix.length - 1;
14         int dC = matrix[0].length - 1;
15         while(tR <= dR && tC <= dC){
16             printEdge(matrix, tR++, tC++, dR--, dC--);
17         }
18     }
19 
20     //打印子矩阵
21     public void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
22         if(tR == dR){ //当子矩阵只有一行时
23             for(int i = tC; i <= dC; i++){
24                 System.out.print(m[tR][i] + " ");
25             }
26         }else if(tC == dC){ //当子矩阵只有一列时
27             for(int i = tR; i <= dR; i++){
28                 System.out.print(m[i][tC] + " ");
29             }
30         }else{ //一般情况
31             int curC = tC;
32             int curR = tR;
33             while(curC != dC){ //向右方向
34                 System.out.print(m[tR][curC++] + " ");
35             }
36             while(curR != dR){ //向下方向
37                 System.out.print(m[curR++][dC] + " ");
38             }
39             while(curC != tC){ //向左方向
40                 System.out.print(m[dR][curC--] + " ");
41             }
42             while(curR != tR){ //向上方向
43                 System.out.print(m[curR--][tC] + " ");
44             }
45         }
46     }
47     
48 }

 

posted @ 2019-03-12 06:36  米突小搞羊  阅读(245)  评论(0编辑  收藏  举报