NC201 对角线遍历矩阵
描述
给定一个大小为 n*m 的矩阵,请以对角线遍历并返回遍历结果
数据范围: ,矩阵中的元素满足
示例1
输入:
[[1,2,3],[4,5,6],[7,8,9]]
返回值:
[1,2,4,7,5,3,6,8,9]
复制
示例2
输入:
[[1,3],[2,4]]
返回值:
[1,3,2,4]
题解
思路:
我们可以先手动画一下,发现Z形走法在遇到边界的时候有2个方向——从右上往坐下走,此时x++,y--;从坐下往右上走,此时x--,y++。因此我们可以定义2个方向{dx=1,dy=-1}和{dx=-1,dy=1}。
另外,在走某一条路的时候,x+y的和是不变的,只有在(x,y)所代表的坐标到达4个边框的时候,才将x与y的和加一,至于需要将x还是y加一,需要根据四种情况进行分析。
- 如果在上边界,也就是x=0的时候,且y < n - 1,则y递增
- 如果在左边界,也就是y=0的时候,且x < m - 1,则x递增
- 如果在右边界,也就是y=n-1的时候,且x < m - 1,则x递增
- 如果在下边界,也就是x = m - 1的时候,且y < n - 1,则y递增
代码如下:
#include <bits/stdc++.h>
using namespace std;
vector<int> diagonalOrder(vector<vector<int>> &mat)
{
int count = mat.size() * mat[0].size();
std::vector<int> ans(count);
int x = 0;
int y = 0;
int m = mat.size();
int n = mat[0].size();
std::vector<std::pair<int, int>> direct = {{-1, 1}, {1, -1}}; // 2个方向:从左下角往右上角走,从右上角往左下角走
int d = 0; // 初始方向其实无所谓,主要是d=1的时候要从右上角往左下角走
while (true)
{
auto dx = direct[d % 2].first;
auto dy = direct[d % 2].second;
d++; // 更新下一次的方向
// 嗯,这里其实可以使用do{}while(conditian)来实现~~
ans.push_back(mat[x][y]); // 将当前坐标放入遍历结果
while ((dx + x >= 0 && dx + x <= m - 1) && (dy + y >= 0 && dy + y <= n - 1)) // 往2个方向走
{
x = dx + x;
y = dy + y;
ans.push_back(mat[x][y]);
}
if (x == m - 1 && y == n - 1) // 已经到达最后一个位置
{
break;
}
// 处理四个边界问题,具体意思看代码自己理解吧~~
if (x == 0 && y < n - 1)
{
x = 0; // 这里的x=0起始是可以不写的,哈,只是为了看着方便点~~
y++;
}
else if (y == 0 && x < m - 1)
{
y = 0;
x += 1;
}
else if (y == n - 1 && x < m - 1)
{
y = n - 1;
x += 1;
}
else if (x == m - 1)
{
y++;
x = m - 1;
}
}
return ans;
}