给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
说明:
- 给定矩阵中的元素总数不会超过 100000 。
分析:
读取一个数字后就计算下一个数字的坐标,然后循环读取,直到结束
首先确定如图所示的箭头走向,要么是左上,要么是右下
如果一直按照箭头的走向,那么一定会越界,所以需要对越界的情况进行区分,针对不同的区域对坐标进行不同的调整
// 1 2 3
// 8 矩阵 4
// 8 区域 4
// 7 6 5
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
// 将整个矩阵区域分为一个九宫格,矩阵区域为0
// 1 2 3
// 8 矩阵 4
// 8 区域 4
// 7 6 5
// 保存结果
vector<int>result;
// 判空
if(matrix.empty())
return result;
// 表示x和y的范围
int x_range = matrix[0].size();
int y_range = matrix.size();
// 表示往左上还是右下
int direction = 1;
// 表示运行到右下角三角形
// bool flag = false;
// 表示当前坐标
int x=0,y=0;
// 计数
int count = 0;
// 直到遍历到最后一个元素
while(count<x_range*y_range){
count ++;
result.push_back(matrix[y][x]);
// cout<<matrix[y][x]<<endl;
// **** 计算下一个数字坐标 ***
// x和y的方向是反的
x += direction;
y -= direction;
// 得到坐标区域
int location = verditc(x_range,x,y_range,y);
switch(location){
// |--------------------> x
// | 1 2 3
// | 8 矩阵 4
// | 8 区域 4
// | 7 6 5
// v
// y
// 判断越界和方向
case 2:
y += 1;
direction *= -1;
break;
case 3:
x -= 1;
y += 2;
direction *= -1;
break;
case 4:
x -= 1;
y += 2;
direction *= -1;
break;
case 6:
x += 2;
y -= 1;
direction *= -1;
break;
case 7:
x += 2;
y -= 1;
direction *= -1;
break;
case 8:
x += 1;
direction *= -1;
break;
case 1:case 5:
// 不可能出现
break;
case 0:
break;
default:
break;
}
}
return result;
}
// 九宫格区域判断
int verditc(int range_x, int x, int range_y, int y){
int location = 0;
// 1 2 3
// 8 矩阵 4
// 8 区域 4
// 7 6 5
if(x < 0){
if(y < 0)
location = 1;
else if(y >= range_y)
location = 7;
else
location = 8;
}else if(x >= range_x){
if(y < 0)
location = 3;
else if(y >= range_y)
location = 5;
else
location = 4;
}else{
if(y < 0)
location = 2;
else if(y >= range_y)
location = 6;
else
location = 0;
}
return location;
}
};