思路:
我们可以先手动画一下,发现Z形走法在遇到边界的时候有2个方向——从右上往坐下走,此时x++,y--;从坐下往右上走,此时x--,y++。因此我们可以定义2个方向{dx=1,dy=-1}和{dx=-1,dy=1}。
另外,在走某一条路的时候,x+y的和是不变的,只有在(x,y)所代表的坐标到达4个边框的时候,才将x或者y加一,至于需要将x还是y加一,需要根据四种情况进行分析。
1. 如果在上边界,也就是x=0的时候,且y < n - 1,则y递增
2. 如果在左边界,也就是y=0的时候,且x < m - 1,则x递增
3. 如果在右边界,也就是y=n-1的时候,且x < m - 1,则x递增
4. 如果在下边界,也就是x = m - 1的时候,且y < n - 1,则y递增
我们可以先手动画一下,发现Z形走法在遇到边界的时候有2个方向——从右上往坐下走,此时x++,y--;从坐下往右上走,此时x--,y++。因此我们可以定义2个方向{dx=1,dy=-1}和{dx=-1,dy=1}。
另外,在走某一条路的时候,x+y的和是不变的,只有在(x,y)所代表的坐标到达4个边框的时候,才将x或者y加一,至于需要将x还是y加一,需要根据四种情况进行分析。
1. 如果在上边界,也就是x=0的时候,且y < n - 1,则y递增
2. 如果在左边界,也就是y=0的时候,且x < m - 1,则x递增
3. 如果在右边界,也就是y=n-1的时候,且x < m - 1,则x递增
4. 如果在下边界,也就是x = m - 1的时候,且y < n - 1,则y递增
注意:
1. 可以不在堆上分配的内存,尽量不要在堆上分配
2. 这里ans的大小实际上是直到的,因此一开始我们就可以分配好需要的内存
以上2个优化,代码直接从超过0%变成了超过100%~~
代码如下:
#include <bits/stdc++.h>
using namespace std;
vector<int> diagonalOrder(vector<vector<int>> &mat)
{
std::vector<int> ans;
int x = 0;
int y = 0;
int m = mat.size();
int n = mat[0].size();
ans.reserve(m * n);
std::pair<int, int> direct[2] = {{-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;
}

京公网安备 11010502036488号