一:对角线遍历
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
思路一:
按遍历方向来按规律往结果res中添加数字,添加的顺序如下:
[0,0] -> [0,1],[1,0] -> [2,0],[1,1],[0,2] -> [1,2],[2,1] -> [2,2]
根据遍历的方向不同共分为五层,关键就是确定每一层的坐标范围:层数=m+n-1
下边界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[0].empty()) return {};
int m = matrix.size(), n = matrix[0].size(), k = 0;
vector<int> res(m * n);
for (int i = 0; i < m + n - 1; ++i)
{
int low = max(0, i - n + 1), high = min(i, m - 1);
if (i % 2 == 0) //偶数层 向↙遍历
{
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;
}
};
思路二:
右上移动:坐标[-1, 1],左下移动:坐标[1, -1]
边界问题:左下角和右上角的位置越界需要改变两个坐标之外,其余的越界只需要改变一个。
同时改变两个坐标的越界情况,即在右上角和左下角的位置。如果在右上角位置还要往右上走时,那么要移动到它下面的位置的,那么:
如果row超过了m-1的范围,那么row重置为m-1,并且col自增2,然后改变遍历的方向。
如果col超过了n-1的范围,那么col重置为n-1,并且row自增2,然后改变遍历的方向。
一般的左边越界情况:如果row小于0,那么row重置0,然后改变遍历的方向。
如果col小于0,那么col重置0,然后改变遍历的方向。
代码:
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty())
return {};
int m = matrix.size(), n = matrix[0].size();
int r = 0, c = 0, k = 0;
vector<int> res(m * n);
vector<vector<int>> dirs{{-1,1}, {1,-1}};
for (int i = 0; i < m * n; ++i) {
res[i] = matrix[r][c];
r += dirs[k][0];
c += dirs[k][1];
if (r >= m) {r = m - 1; c += 2; k = 1 - k;}
if (c >= n) {c = n - 1; r += 2; k = 1 - k;}
if (r < 0) {r = 0; k = 1 - k;}
if (c < 0) {c = 0; k = 1 - k;}
}
return res;
}
};
二、螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
思路:
1 2 3
+ 6 + + + 5
9 4
8 7
上边:up=0,下边down=m-1,左边left=0,右边right=n-1
进行while循环,先遍历上边,将所有元素加入结果res,然后上边下移一位,如果此时上边大于下边,说明此时已经遍历完成了,直接break(即只有一行)。
同理对于下边,左边,右边
代码:
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.empty() || matrix[0].empty()) return {};
int m = matrix.size(), n = matrix[0].size();
vector<int> res;
int up = 0, down = m - 1, left = 0, right = n - 1;
while (true) {
for (int j = left; j <= right; ++j) res.push_back(matrix[up][j]);
if (++up > down) break;//只有一行
for (int i = up; i <= down; ++i) res.push_back(matrix[i][right]);
if (--right < left) break;//只有一列
for (int j = right; j >= left; --j) res.push_back(matrix[down][j]);
if (--down < up) break;//只有两行
for (int i = down; i >= up; --i) res.push_back(matrix[i][left]);
if (++left > right) break;//只有两列
}
return res;
}
};
三、杨辉三角
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在杨辉三角中,每个数是它左上方和右上方的数的和。
示例:
输入: 5 输出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
思路:特殊:输入1 输出[1]
输入2 输出[1,1]
一般:x[i][j] = x[i-1][j] + x[i-1][j-1]
代码:
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> res;
if(numRows==0) return res;
res.push_back(vector<int>(1,1));
if(numRows==1) return res;
res.push_back(vector<int>(2,1));
if(numRows==2) return res;
for(int i=2;i<numRows;i++)
{
vector<int> tmp(i+1,1);
for(int j=1;j<i;j++)
{
tmp[j]=res[i-1][j-1]+res[i-1][j];
}
res.push_back(tmp);
}
return res;
}
};