跟左神学算法_4 基础数据结构(矩阵相关)

内容:

1、转圈打印矩阵问题

2、旋转正方形矩阵问题

3、之字形打印矩阵问题

4、在行和列都排序好的矩阵中找数

1、转圈打印矩阵问题

问题描述:

 1 给定一个整形矩阵matrix,请按照转圈的方式打印它。
 2             
 3     例如:        
 4         1    2    3    4            
 5         5    6    7    8        
 6         9    10   11   12        
 7         13   14   15   16
 8             
 9     打印结果为: 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
10     要求额外空间复杂度为O(1)

解决思路:

一圈一圈的打印,比如上面的1到16到1为1圈,6到11到6为1圈,主要就是要注意边界问题

代码:

 1 public class RotateOutputMatrix {
 2     private int M;
 3     private int N;
 4     private int[][] arr;
 5     private final int startValue = 1;
 6         
 7         // 初始化矩阵
 8     public RotateOutputMatrix(int M, int N) {
 9         this.M = M;
10         this.N = N;
11         int value = startValue;
12         arr = new int[M][N];
13         for (int i = 0; i < M; i++) {
14             for (int j = 0; j < N; j++) {
15                 this.arr[i][j] = value++;
16             }
17         }
18     }
19 
20     public void printEdge(int a, int b, int c, int d) {
21         // 输出一层
22         // (a, b) -> 左上角 (c, d) -> 右下角
23         if (b == d) {
24             // 两个点在一列上
25             for (int i = a; i <= c; i++) {
26                 System.out.print(arr[i][b] + " ");
27             }
28         } else if (a == c) {
29             // 两个点在一行上
30             for (int j = b; j <= d; j++) {
31                 System.out.print(arr[a][j] + " ");
32             }
33         } else {
34             // 两个点不在一行也不在一列上 -> 两个点在对角线上
35             int curA = a;
36             int curB = b;
37             while (curB < d) {
38                 System.out.print(arr[curA][curB] + " ");
39                 curB++;
40             }
41             while (curA < c) {
42                 System.out.print(arr[curA][curB] + " ");
43                 curA++;
44             }
45             while (curB > b) {
46                 System.out.print(arr[curA][curB] + " ");
47                 curB--;
48             }
49             while (curA > a) {
50                 System.out.print(arr[curA][curB] + " ");
51                 curA--;
52             }
53         }
54     }
55 
56     public void printAllEdge() {
57         // 输出所有的层
58         int a = 0;
59         int b = 0;
60         int c = this.M - 1;
61         int d = this.N - 1;
62         while (a <= c && b <= d) {
63             printEdge(a++, b++, c--, d--);
64         }
65     }
66     
67     // test
68     public void printMartix(){
69         for(int i=0; i<arr.length; i++){
70             for(int j=0; j<arr[0].length; j++){
71                 System.out.print(arr[i][j] + " ");
72             }
73             System.out.println();
74         }
75     }
76 
77     public static void main(String[] args) {
78         RotateOutputMatrix test = new RotateOutputMatrix(4, 4);
79         test.printMartix();
80         System.out.println("=================");
81         test.printAllEdge();
82     }
83 }

2、旋转正方形矩阵问题

问题描述:

给定一个整型正方形矩阵matrix,请把该矩阵调整成 顺时针旋转90度的样子

思路:

和上面那道题类似,一层一层的转,每一层中又可以分成若干旋转次数进行转(旋转次数=边上的元素个数-1)

比如:

1 2 3 

4 5 6

7 8 9

最外层是1 2 3 6 9 8 7 4 可以先转1 3 9 7 再转 2 6 8 4

代码:

 1 public class RotateSquare90 {
 2     private int M;
 3     private int[][] arr;
 4     private final int startValue = 1;
 5 
 6     public RotateSquare90(int M) {
 7         this.M = M;
 8         int value = startValue;
 9         arr = new int[M][M];
10         for (int i = 0; i < M; i++) {
11             for (int j = 0; j < M; j++) {
12                 this.arr[i][j] = value++;
13             }
14         }
15     }
16 
17     public void rotateEdge(int a, int b, int c, int d) {
18         // 旋转一层
19         int times = c - a;
20         int tmp = 0;
21         for (int i = 0; i < times; i++) {
22             tmp = arr[a][b + i];
23             arr[a][b + i] = arr[c - i][b];
24             arr[c - i][b] = arr[c][d - i];
25             arr[c][d - i] = arr[a + i][d];
26             arr[a + i][d] = tmp;
27         }
28     }
29 
30     public void rotateAllEdge() {
31         // 旋转所有层
32         int i = 0;
33         int j = 0;
34         int m = this.M - 1;
35         int n = this.M - 1;
36         while(i<=m&&j<=n){
37             rotateEdge(i++, j++, m--, n--);
38         }
39     }
40 
41     // for test
42     public void printMatrix() {
43         int[][] m = this.arr;
44         for (int i = 0; i < m.length; i++) {
45             for (int j = 0; j < m[0].length; j++) {
46                 System.out.print(m[i][j] + " ");
47             }
48             System.out.println();
49         }
50     }
51 
52     public static void main(String[] args) {
53         RotateSquare90 test = new RotateSquare90(4);
54         test.printMatrix();
55         test.rotateAllEdge();
56         test.printMatrix();
57     }
58 
59 }

3、之字形打印矩阵问题

问题描述:

给定一个矩阵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层,用一个布尔值表示是从上到下还是从下到上,然后最外层控制从开始到结束

代码:

 1 public class ZigZagPrintMatrix {
 2     private int M;
 3     private int N;
 4     private int[][] arr;
 5     private final int startValue = 1;
 6 
 7     public ZigZagPrintMatrix(int M, int N) {
 8         this.M = M;
 9         this.N = N;
10         int value = startValue;
11         arr = new int[M][N];
12         for (int i = 0; i < M; i++) {
13             for (int j = 0; j < N; j++) {
14                 this.arr[i][j] = value++;
15             }
16         }
17     }
18 
19     public void printLevel(int a, int b, int c, int d, boolean f) {
20         // 打印一条斜线 f为true表示从右上到左下打印 
21         if (f) {
22             // (a, b) -> (c, d)
23             while (a != c + 1) {
24                 System.out.print(arr[a++][b--] + " ");
25             }
26         } else {
27             // (c, d) -> (a, b)
28             while (d != b + 1) {
29                 System.out.print(arr[c--][d++] + " ");
30             }
31         }
32     }
33 
34     public void printMatrixZigZag() {
35         // 打印所有斜线
36         int a = 0;
37         int b = 0;
38         int c = 0;
39         int d = 0;
40         int endR = M - 1;
41         int endC = N - 1;
42         boolean fromUp = false;
43         while (a != endR + 1) {
44             printLevel(a, b, c, d, fromUp);
45             a = b == endC ? a + 1 : a;
46             b = b == endC ? b : b + 1;
47             d = c == endR ? d + 1 : d;
48             c = c == endR ? c : c + 1;
49             fromUp = !fromUp;
50         }
51         System.out.println();
52     }
53 
54     // test
55     public void printMartix() {
56         for (int i = 0; i < arr.length; i++) {
57             for (int j = 0; j < arr[0].length; j++) {
58                 System.out.print(arr[i][j] + " ");
59             }
60             System.out.println();
61         }
62     }
63 
64     public static void main(String[] args) {
65         ZigZagPrintMatrix test = new ZigZagPrintMatrix(3, 4);
66         test.printMartix();
67         test.printMatrixZigZag();
68     }
69 }

4、在行和列都排序好的矩阵中找数

问题描述:

1 给定一个N×M的整型矩阵matrix和一个正数K,matrix的每一行每一列都是排好序的。实现一个函数,判断K是否在matrix中
2     例如: 
3       0, 1, 2, 5 
4       2, 3, 4, 7 
5       4, 4, 4, 8 
6       5, 7, 7, 9 
7     如果K为7,返回True;如果K为6,返回False。 
8     要求时间复杂度O(N+M),空间复杂度O(1)

思路:

1 思路: 从右上角开始对比 如果当前数比K大那么当前数往左走 如果当前数比K小那么当前数往下走
2           直到找到数K或者数走到边界不能再走为止 时间复杂度为O(N+M)
3         
4         O(N+M)对应的最坏情况(找不到数或数就在左下角的位置):
5             1 3 5 6
6             2 5 7 9 
7             4 6 8 10   
8             k = 4    

代码:

 1 private static boolean find(int[][] arr, int num) {
 2     int row = 0;
 3     int col = arr[0].length - 1;
 4     while (row != arr[0].length - 1 && col != 0) {
 5         if (arr[row][col] == num) {
 6             return true;
 7         } else if (arr[row][col] > num) {
 8             col--;
 9         } else {
10             row++;
11         }
12     }
13 
14     return false;
15 }

猜你喜欢

转载自www.cnblogs.com/wyb666/p/10159403.html
今日推荐