之字形打印矩阵

之字形打印矩阵

一、题目

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

也就是按照 “之” 字形的方式打印这个矩阵

1
2
mat = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,4,7,5,3,6,8,9]

二、思路

我们可以看到其实就是按照对角线来打印。我们选取两个坐标。

第一个坐标从 (0,0)位置,先遍历行,到达行结尾了再遍历列。如下:

1
(0,0) -> (0,1) -> (0,2) -> (0,3) -> (1,3) -> (2,3) -> (3,3)

第二个坐标从 (0,0) 位置,先遍历列,达到列结尾了再遍历行。如下:

1
(0,0) -> (1,0) -> (2,0) -> (3,0) -> (3,1) -> (3,2) -> (3,3)

我们只需要每次读取两个坐标之间的元素,这两个坐标之间的元素就是对角线之间的元素。遍历顺序我们可以使用一个 bool 值来区分,每次取反就可以了

三、代码

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
#include <vector>
#include <iostream>

class Solution {
public:
std::vector<int> findDiagonalOrder(const std::vector<std::vector<int>>& mat) {
std::vector<int> res;
if (mat.empty()) {
return res;
}
int row = mat.size() - 1, line = mat[0].size() - 1;
int tr = 0, tc = 0;
int dr = 0, dc = 0;
bool flag = true;
for (; tr <= row && tc <= line && dr <= row && dc <= line;) {
int i = flag ? dr : tr;
int j = flag ? dc : tc;
for (;;) {
res.push_back(mat[i][j]);
if (flag) {
i--, j++;
if (i < tr && j > tc) {
break;
}
} else {
i++, j--;
if (i > dr && j < dc) {
break;
}
}
}
if (tc == line) {
tr++;
} else {
tc++;
}
if (dr == row) {
dc++;
} else {
dr++;
}
flag = !flag;
}
return res;
}
};

void print_vec(const std::vector<int>& res) {
for (const auto& x : res) {
std::cout << x << " ";
}
std::cout << std::endl;
}

int main() {
Solution s;
std::vector<std::vector<int>> mat{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
auto res = s.findDiagonalOrder(mat);
print_vec(res);
return 0;
}

时间复杂度:O(N*N) ,空间复杂度:O(N*N)