Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal order as shown in the below image.

Example:

Input:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
Output: [1,2,4,7,5,3,6,8,9]
Explanation:

Note:

  1. The total number of elements of the given matrix will not exceed 10,000.

这道题给了我们一个mxn大小的数组,让我们进行对角线遍历,先向右上,然后左下,再右上,以此类推直至遍历完整个数组,题目中的例子和图示也能很好的帮我们理解。由于移动的方向不再是水平或竖直方向,而是对角线方向,那么每移动一次,横纵坐标都要变化,向右上移动的话要坐标加上[-1, 1],向左下移动的话要坐标加上[1, -1],那么难点在于我们如何处理越界情况,越界后遍历的方向怎么变换。向右上和左下两个对角线方向遍历的时候都会有越界的可能,但是除了左下角和右上角的位置越界需要改变两个坐标之外,其余的越界只需要改变一个。那么我们就先判断要同时改变两个坐标的越界情况,即在右上角和左下角的位置。如果在右上角位置还要往右上走时,那么要移动到它下面的位置的,那么如果col超过了n-1的范围,那么col重置为n-1,并且row自增2,然后改变遍历的方向。同理如果row超过了m-1的范围,那么row重置为m-1,并且col自增2,然后改变遍历的方向。然后我们再来判断一般的越界情况,如果row小于0,那么row重置0,然后改变遍历的方向。同理如果col小于0,那么col重置0,然后改变遍历的方向。参见代码如下:

解法一:

class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
int m = matrix.size(), n = matrix[].size(), r = , c = , k = ;
vector<int> res(m * n);
vector<vector<int>> dirs{{-,}, {,-}};
for (int i = ; i < m * n; ++i) {
res[i] = matrix[r][c];
r += dirs[k][];
c += dirs[k][];
if (r >= m) {r = m - ; c += ; k = - k;}
if (c >= n) {c = n - ; r += ; k = - k;}
if (r < ) {r = ; k = - k;}
if (c < ) {c = ; k = - k;}
}
return res;
}
};

下面这种方法跟上面的方法思路相同,不过写法有些不同,这里根据横纵左边之和的奇偶性来判断遍历的方向,然后对于越界情况再单独处理即可,参见代码如下:

解法二:

class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
int m = matrix.size(), n = matrix[].size(), r = , c = ;
vector<int> res(m * n);
for (int i = ; i < m * n; ++i) {
res[i] = matrix[r][c];
if ((r + c) % == ) {
if (c == n - ) {++r;}
else if (r == ) {++c;}
else {--r; ++c;}
} else {
if (r == m - ) {++c;}
else if (c == ) {++r;}
else {++r; --c;}
}
}
return res;
}
};

下面这种方法是按遍历方向来按规律往结果res中添加数字的,比如题目中的那个例子,那么添加的顺序如下:

[0,0] -> [0,1],[1,0] -> [2,0],[1,1],[0,2] -> [1,2],[2,1] -> [2,2]

根据遍历的方向不同共分为五层,关键就是确定每一层的坐标范围,其中下边界low = max(0, i - n + 1),这样可以保证下边界不会小于0,而上边界high = min(i, m - 1),这样也保证了上边界不会大于m-1,如果是偶数层,则从上边界往下边界遍历,反之如果是奇数层,则从下边界往上边界遍历,注意从matrix中取数字的坐标,,参见代码如下:

解法三:

class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
int m = matrix.size(), n = matrix[].size(), k = ;
vector<int> res(m * n);
for (int i = ; i < m + n - ; ++i) {
int low = max(, i - n + ), high = min(i, m - );
if (i % == ) {
for (int j = high; j >= low; --j) {
res[k++] = matrix[j][i - j];
}
} else {
for (int j = low; j <= high; ++j) {
res[k++] = matrix[j][i - j];
}
}
}
return res;
}
};

下面这种方法就有一点暴力搜索的感觉,不像上面一种精确计算每一层的坐标范围,这种方法是利用对角线上的数字的横纵坐标之和恒定这一特性来搜索的,然后把和为特定值的数字加入结果res中,参见代码如下:

解法四:

class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[].empty()) return {};
int m = matrix.size(), n = matrix[].size(), k = ;
vector<int> res;
for (int k = ; k < m + n - ; ++k) {
int delta = - * (k % == );
int ii = (m - ) * (k % == );
int jj = (n - ) * (k % == );
for (int i = ii; i >= && i < m; i += delta) {
for (int j = jj; j >= && j < n; j += delta) {
if (i + j == k) {
res.push_back(matrix[i][j]);
}
}
}
}
return res;
}
};

参考资料:

https://discuss.leetcode.com/topic/77866/short-bf-solution

https://discuss.leetcode.com/topic/77865/concise-java-solution/2

https://discuss.leetcode.com/topic/77862/my-8ms-short-solution-9line

https://discuss.leetcode.com/topic/77937/java-15-lines-without-using-boolean

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Diagonal Traverse 对角线遍历的更多相关文章

  1. 498 Diagonal Traverse 对角线遍历

    详见:https://leetcode.com/problems/diagonal-traverse/description/ C++: class Solution { public: vector ...

  2. Leetcode 498:对角线遍历Diagonal Traverse(python3、java)

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

  3. 498. Diagonal Traverse对角线z型traverse

    [抄题]: Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in dia ...

  4. [Swift]LeetCode498. 对角线遍历 | Diagonal Traverse

    Given a matrix of M x N elements (M rows, N columns), return all elements of the matrix in diagonal ...

  5. 【LeetCode】498. Diagonal Traverse 解题报告(Python)

    [LeetCode]498. Diagonal Traverse 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: htt ...

  6. LeetCode:对角线遍历【498】

    LeetCode:对角线遍历[498] 题目描述 给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示. 示例: 输入: [ [ ...

  7. Leetcode 498.对角线遍历

    对角线遍历 给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示. 示例: 输入: [ [ 1, 2, 3 ], [ 4, 5, ...

  8. 498. (leetcode)对角线遍历

    498. 对角线遍历 根据题目的图像看,主要有两种走法,第一种是向右上(顺时针方向),第二种是向左下(逆时针)走 我们设 x ,y初始为0,分别对应横纵坐标 现在分析右上(0,2) 为例:(注意右上的 ...

  9. Java实现 LeetCode 498 对角线遍历

    498. 对角线遍历 给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示. 示例: 输入: [ [ 1, 2, 3 ], [ ...

随机推荐

  1. 让Myeclipse自动生成的get set方法 自动加上文本注释,并且注释内容包含字段中我们加的文档注释

    在进行编码写实体类的时候发现,一个实体类有好多的字段要进行注释,他们都是私有的不能直接访问,我们在写的时候加入的文档注释也起不到效果,但是自动生成的get,set方法的文档注释有不符合我们要求(没有包 ...

  2. nvm配置

    多版本安装方式 卸载已有的Node.js 下载nvm 在C盘创建目录dev 在dev目中中创建两个子目录nvm和nodejs 并且把nvm包解压进去nvm目录中 在install.cmd文件上面右键选 ...

  3. 阿里聚安全·安全周刊】一种秘密窃取数据的新型 Android 木马|iOS 11相机惊现BUG

    本周的七个关键词:  新型 Android 木马丨 TLS 1.3 丨  阿里安全图灵实验室 丨 漏洞感染 Linux 服务器 丨 CPU曝极危漏洞 丨   iOS 11相机BUG 丨R2D2技术 - ...

  4. @Cacheable的实现原理

    如果你用过Spring Cache,你一定对这种配置和代码不陌生: <cache:annotation-driven cache-manager="cacheManager" ...

  5. 20162330 第十二周 蓝墨云班课 hash

    题目要求 利用除留余数法为下列关键字集合的存储设计hash函数,并画出分别用开放寻址法和拉链法解决冲突得到的空间存储状态(散列因子取0.75) 关键字集合:85,75,57,60,65,(你的8位学号 ...

  6. 高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告

    高级软件工程2017第6次作业--团队项目:Alpha阶段综合报告 Deadline:2017-10-30(周一)21:00pm (注:以下内容参考集大作业4,集大作业5,集大作业6,集大作业7 一. ...

  7. TSP-旅行商问题

    #include <iostream> #include <vector> #include <algorithm> using namespace std; in ...

  8. [译]RabbitMQ教程C#版 - 工作队列

    先决条件 本教程假定RabbitMQ已经安装,并运行在localhost标准端口(5672).如果你使用不同的主机.端口或证书,则需要调整连接设置. 从哪里获得帮助 如果您在阅读本教程时遇到困难,可以 ...

  9. express学习(二)—— Post()类型和中间件

    1.数据:GET.POST 2.中间件:使用.写.链式操作 GET-无需中间件 req.query POST-需要"body-parser" server.use(bodyPars ...

  10. mysql 查询select语句汇总

    数据准备: 创建表: create table students( id int unsigned primary key auto_increment not null, name varchar( ...