题解 | #对角线遍历矩阵#

对角线遍历矩阵

https://www.nowcoder.com/practice/04b591e3537046c68bf398c18b84cb27

思路:

我们可以先手动画一下,发现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;
}


全部评论

相关推荐

后端彭于晏:你无敌了
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务