【Leetcode】498. 对角线遍历

QUESTION

medium

题目描述

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示

输入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

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

498-1

说明

  • 给定矩阵中的元素总数不会超过 100000

SOLUTION

这个问题需要注意边界的控制

方法一(按层访问)

这个方法就很暴力了,直接分两种情况代入

  • 先来看看单往右下的对角线访问
//单右往下
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
    vector<int> res;
    if(matrix.empty()) return res;
    const int m = matrix.size();
    const int n = matrix[0].size();
    for(int l = 0; l < m + n - 1; l++){
        int i = (l < n ? 0 : (l - n + 1));
        int j = (l < n ? l : (n - 1));
        while(i < m && j >= 0){
            res.push_back(matrix[i][j]);
            i++;
            j--;
        }
    }
    return res;
}
  • 同理可以写出单往左上的对角线访问
//单左往上
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
    vector<int> res;
    if(matrix.empty()) return res;
    const int m = matrix.size();
    const int n = matrix[0].size();
    for(int l = 0; l < m + n - 1; l++){
        int i = (l < m ? l : (m - 1));
        int j = (l < m ? 0 : (l - m + 1));
        while(i >= 0 && j < n){
            res.push_back(matrix[i][j]);
            i--;
            j++;
        }
    }
    return res;
}

合并一下情况就可以写出如下代码:

vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
    vector<int> res;
    if(matrix.empty()) return res;
    const int m = matrix.size();
    const int n = matrix[0].size();
    for(int l = 0; l < m + n - 1; l++){
        if(l % 2 == 0){ //左往上
            int i = (l < m ? l : (m - 1));
            int j = (l < m ? 0 : (l - m + 1));
            while(i >= 0 && j < n){
                res.push_back(matrix[i][j]);
                i--;
                j++;
            }
        }
        else{
            int i = (l < n ? 0 : (l - n + 1));
            int j = (l < n ? l : (n - 1));
            while(i < m && j >= 0){
                res.push_back(matrix[i][j]);
                i++;
                j--;
            }
        }
    }
    return res;
}

这个办法主要是要注意每层索引的起始值以及边界

方法二

看了Leetcode关于本题一些评论发现了如下的解释

利用每层的索引和相等

  1. 假设矩阵无限大
  2. 索引和为{偶}数,向上遍历,{横}索引值递减,遍历值依次是(x,0),(x-1,1),(x-2,2),…,(0,x)
  3. 索引和为{奇}数,向下遍历,{纵}索引值递减,遍历值依次是(0,y),(1,y-1),(2,y-2),…,(y,0)
0:              (00)
1:            (01)(10)
2:          (20)(11)(02)
3:        (03)(12)(21)(30)
4:      (40)(31)(22)(13)(04)
5:    (05)(14)(23)(32)(41)(50)
6:  (60)(51)................(06)

按照如上的规律,我们可以写出如下的方法

vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
    vector<int> res;
    if(matrix.empty()) return res;
    const int m = matrix.size(); //行数
    const int n = matrix[0].size(); //列数
    int i = 0;
    int j = 0;
    for(int l = 0; l < m*n; l++){
        res.push_back(matrix[i][j]);
        if((i + j) % 2 == 0){ //左往上遍历
            if(j == n - 1){ //列坐标到达右边界
                i++; //往下移一格准备右往下遍历
            }
            else if(i == 0){ //行坐标到顶部了
                j++; //往右移一格准备右往下遍历
            }
            else{ //往右上移动一格
                i--;
                j++;
            }
        }
        else{ //右往下遍历
            if(i == m - 1){
                j++;
            }
            else if(j == 0){
                i++;
            }
            else{
                i++;
                j--;
            }
        }
        return res;
    }
}

这种办法是每一次循环遍历一个,然后切换至下一个位置,主要是要注意边界的转换,同时利用了每层索引和相同的规律,比方法一更加精妙一些

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值