我是靠谱客的博主 爱听歌钢笔,这篇文章主要介绍《剑指offer》面试题29:顺时针打印矩阵,现在分享给大家,希望可以做个参考。

更多剑指offer面试习题请点击:《剑指offer》(第二版)题集目录索引

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:

复制代码
1
2
3
4
5
6
/* 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。

解题思路:
    这题我们可以把一个矩阵想象成若干个圈套在一起组成。我们可以用一个循环来打印矩阵,每次打印矩阵中的一个圈。

    下面分析循环结束条件。假设这个矩阵行数是rows,列数是columns。打印第一圈的第一个数的坐标是(0, 0),第二圈的第一个数的坐标是(1, 1),所以我们可以推出,每圈第一个数的行坐标和列坐标是相同的。

    对于一个5×5的矩阵而言,最后一圈只有一个数,它的坐标是(2, 2),并且5>2×2。对于一个6×6的矩阵而言,最后一圈只有4个数,第一个数字的坐标是(2, 2),而且6>2×2依旧成立。所以我们得出结论循环继续的条件是columns>startX×2且rows>startY×2。所以打印矩阵可以使用如下循环:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void PrintMatrixClockwisely(int** numbers, int columns, int rows) { if (numbers == NULL || columns <= -0 || rows <= 0) return; int start = 0; while (columns > start * 2 && rows > start * 2) { PrintMatrixInCircle(numbers, columns, rows, start); start++; } }

    我们已经把循环打印矩阵的程序写好了,接下来就是要写打印一圈矩阵的程序。我们把打印一圈矩阵分为四步:第一步,从左到右打印一行;第二步,从上到下打印一列;第三步,从右到左打印一行;第四步,从下到上打印一列。每一步我们根据起始坐标和终止坐标设计一个循环就能打印一行或一列。

    但要注意,有可能最后一圈只有一行、只有一列或者只有一个数,那打印一圈就不需要四步了。接下来我们要分析在什么情况下打印一圈需要四步;在什么情况下打印一圈需要三步;在什么情况下打印一圈需要两步;在什么情况下打印一圈只需要一步;

  1. 只要进入了while开始打印,那第一步就是必备的,这点无可争议。如果这一圈只有一行 那就不需要第二步了。
  2. 当这一圈有两行或两行以上,那就需要第二步。即终止行号大于起始行号。
  3. 当这一圈有两行两列的时候,那就需要第三步。即终止行号大于起始行号且终止列号大于起始列号。
  4. 最后一圈有三行两列是就需要第四步。即终止行号比起始行号至少大2且终止列号大于起始列号。

        通过上面的分析我们可以写出如下代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void PrintMatrixInCircle(int** numbers, int columns, int rows, int start) { int endX = columns - 1 - start; //终止列号 int endY = rows - 1 - start; //终止行号 /*第一步:打印从左到右这一行*/ for (int i = start; i <= endX; i++) { /*行号不变,列号增加*/ int number = numbers[start][i]; printNumber(number); } /*第二步:打印从上到下这一列,终止行号大于起始行号*/ if (start < endY) { for (int i = start + 1; i <= endY; i++) { /*行号增加,列号不变*/ int number = numbers[i][endX]; printNumber(number); } } /*第三步:打印从右到左这一行,终止行号大于起始行号且终止列号大于起始列号。*/ if (start < endX &&start < endY) { for (int i = endX - 1; i >= start; i--) { /*行号不变,列号减少*/ int number = numbers[endY][i]; printNumber(number); } } /*第四步:打印从下到上这一列,终止行号比起始行号至少大2且终止列号大于起始列号。*/ if (start < endX && start < endY - 1) { for (int i = endY - 1; i >= start + 1; i--) { /*行号减少,列号不变*/ int number = numbers[i][start]; printNumber(number); } } }

    最后完善打印单个数字代码。

复制代码
1
2
3
4
void printNumber(int number) { printf("%dt", number); }

测试代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
void Test(int columns, int rows) { printf("Test Begin: %d columns, %d rows.n", columns, rows); if(columns < 1 || rows < 1) return; int** numbers = new int*[rows]; for(int i = 0; i < rows; ++i) { numbers[i] = new int[columns]; for(int j = 0; j < columns; ++j) { numbers[i][j] = i * columns + j + 1; } } PrintMatrixClockwisely(numbers, columns, rows); printf("n"); for(int i = 0; i < rows; ++i) delete[] (int*)numbers[i]; delete[] numbers; } int main(int argc, char* argv[]) { /* 1 */ Test(1, 1); /* 1 2 3 4 */ Test(2, 2); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ Test(4, 4); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 */ Test(5, 5); /* 1 2 3 4 5 */ Test(1, 5); /* 1 2 3 4 5 6 7 8 9 10 */ Test(2, 5); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ Test(3, 5); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ Test(4, 5); /* 1 2 3 4 5 */ Test(5, 1); /* 1 2 3 4 5 6 7 8 9 10 */ Test(5, 2); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ Test(5, 3); /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 */ Test(5, 4); system("pause"); return 0; }

运行结果:
这里写图片描述

最后

以上就是爱听歌钢笔最近收集整理的关于《剑指offer》面试题29:顺时针打印矩阵的全部内容,更多相关《剑指offer》面试题29内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(100)

评论列表共有 0 条评论

立即
投稿
返回
顶部