您的位置:首页 > Web前端

【剑指Offer】19:顺时针打印矩阵

2020-03-31 19:41 656 查看

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 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.

题解一:循环转向
1 public static ArrayList<Integer> printMatrix(int [][] matrix) {
2             ArrayList<Integer> result=new ArrayList<Integer>();
3             if(matrix.length==0) {
4                 return result;
5             }
6             //初始化矩阵行数和列数
7             int row=matrix.length,column=matrix[0].length;
8             if(column==0) {
9                 //如果矩阵行数不为0,矩阵的列数为0,意味着矩阵由空元素组成,依然返回空列表
10                 return result;
11             }
12             /*
13              * layers是循环遍历的层数,由行和列的较小值决定,-1是为了考虑较小值为奇数的情况,
14              * 除以2是因为每次循环都会因顶部从左到右和底部从右到左而用掉2行,所以只取一半,
15              * +1是为了补偿之前-1造成的奇数情况下的0.5层以及偶数情况下少1层
16              */
17             int layers=(Math.min(row,column)-1)/2+1;
18             for(int i=0;i<layers;i++){
19                 /*
20                  * 从左上到右上是从对角线元素开始,因为每上一轮的从左下到左上会多用掉1个当前行前面的元素,所以一开始j=i。
21                  * 遍历索引小于矩阵列数减去当前循环层数,因为前几轮从右上到右下会用掉当前行后面的元素
22                  * */
23                 for(int j=i;j<column-i;j++){
24                     result.add(matrix[i][j]);
25                 }
26                 /*
27                  * 从右上到右下,因为这一轮的从左上到右上会多用掉当前列上面的1个元素,所以一开始k=i+1。
28                  * 遍历索引小于矩阵行数减去当前循环层数,因为前几轮从右下到左下会用掉当前列下面的元素。
29                  * 矩阵列的最大索引为column-1(从0开始),所以填充列表result的元素列号为列最大索引减去循环层数,
30                  * 因为前几轮从右上到右下会用掉当前列后几列的元素
31                  * */
32                 for(int k=i+1;k<row-i;k++) {
33                     result.add(matrix[k][column-1-i]);
34                 }
35                 /*
36                  * 从右下到左下,矩阵列的最大索引为column-1(从0开始),因为这一轮的从右上到右下多用了一个当前行后面的元素,再结合前几轮从右
37                  * 上到右下用掉的后面i个元素,所以一开始j=column-1-i-1。
38                  * 从右下到左下过程中最后当前列的索引要大于等于循环层数,因为前几轮从左下到左上用掉了前i-1列元素,所以j>=i。
39                  * 同时考虑矩阵行数小于列数(如3行6列)的情况,使行的最大索引row-1(行号从0开始)减去当前循环层数不会等于当前循环层数,
40                  * 否则最后一轮从左上到右上之后,接下来会再重复这一轮同样元素的从右下到左下。
41                  * 填充列表result的元素行号为行最大索引减去循环层数,因为前几轮从右下到左下会用掉当前行下面几行的元素
42                  * */
43                 for(int j=column-2-i;(j>=i)&&(row-1-i!=i);j--) {
44                     result.add(matrix[row-1-i][j]);
45                 }
46                 /*
47                  * 从左下到左上,矩阵行的最大索引为row-1(从0开始),因为这一轮的从右下到左下多用了1个当前列后面的元素,再结合前几轮从
48                  * 左下到左上用掉的下面i个元素,所以一开始k=row-1-i-1。
49                  * 从左下到左上过程中最后当前行的索引要大于循环层数,和上一行的j>=i不同,
50                  * 这里如果有了等号最后会重复到这一轮的从左上到右上过程的第一个元素,所以k>i。
51                  * 同时考虑矩阵列数小于行数(如6行3列)的情况,使列的最大索引column-1减去当前循环层数不会等于当前循环层数
52                  * ,否则最后一轮从右上到右下后,接下来会再重复这一轮同样元素的从左下到左上。
53                  * 填充列表result的元素列号与当前一轮从左上到右上的开头元素的列索引相同,都为i
54                  * */
55                 for(int k=row-2-i;(k>i)&&(column-1-i!=i);k--) {
56                     result.add(matrix[k][i]);
57                 }
58             }
59             return result;
60         }
题解二:转圈打印
1 private static ArrayList<Integer> list = new ArrayList<>();
2     public ArrayList<Integer> printMatrix01(int [][] matrix) {
3         int rows = matrix.length;
4         int columns = matrix[0].length;
5         int start = 0;
6         while(rows > start*2 && columns > start*2){
7             printMatrixInCircle(matrix, rows, columns, start);
8             start++;
9         }
10         return list;
11     }
12     public static void printMatrixInCircle(int [][] matrix, int rows, int columns, int start){
13         // 从左到右打印一行
14         for(int i = start; i < columns - start; i++) {
15             list.add(matrix[start][i]);
16         }
17         // 从上到下打印一列
18         for(int j = start + 1; j < rows - start; j++) {
19             list.add(matrix[j][columns - start - 1]);
20         }
21         // 从右到左打印一行
22         for(int m = columns - start - 2; m >= start && rows - start - 1 > start; m--) {
23             list.add(matrix[rows - start - 1][m]);
24         }
25         // 从下到上打印一列
26         for(int n = rows - start - 2; n >= start + 1 && columns - start - 1 > start; n--) {
27             list.add(matrix
[start]);
28         }
29     }
题解三:矩形翻转
1 public static ArrayList<Integer> printMatrix02(int [][] matrix) {
2         //作为存放结果的容器
3         ArrayList<Integer> list = new ArrayList<>();
4         //拿到出事数组的行数
5         int row = matrix.length;
6         while(row != 0){
7             //将数组的第一行先添加进容器中
8             for(int i=0;i<matrix[0].length;i++) {
9                 list.add(matrix[0][i]);
10             }
11             //当行数等于1时就没有必要再继续执行了,在上面打印完之后就可以停止了
12             if(row == 1){
13                 break;
14             }
15             //删除上面遍历的数组的第一行,然后旋转这个数组并返回
16             matrix = revert(matrix);
17             //更新行数
18             row = matrix.length;
19         }
20         //返回
21         return list;
22     }
23     private static int[][] revert(int[][] matrix){
24         //拿到matrix的行数和列数
25         int rows = matrix.length;
26         int cols = matrix[0].length;
27        //因为我们要将原数组遍历过的第一行删除,然后旋转变成一个新的数组,所以先初始化一下这个新数组
28         int[][] newMatrix = new int[cols][rows-1];
29         //对这个新数组进行赋值
30         for(int j=cols-1;j>=0;j--){
31             for(int i=1;i<rows;i++){
32                 newMatrix[cols-j-1][i-1] = matrix[i][j];
33             }
34         }
35         //返回新数组
36         return newMatrix;
37     }

测试:

1 public static void main(String[] args) {
2         int[][] matrix={{1, 2 ,3, 4},{5, 6, 7 ,8},{9 ,10 ,11 ,12 },{13 ,14, 15, 16}};
3         ArrayList<Integer> list = printMatrix(matrix);
4         for (Integer integer : list) {
5             System.out.print(integer+" ");
6         }
7     }
8 输出:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

 

  • 点赞
  • 收藏
  • 分享
  • 文章举报
Blog_pc 发布了66 篇原创文章 · 获赞 0 · 访问量 292 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: