二维数组花式遍历(旋转,螺旋) [labuladong-刷题打卡 day5]
矩阵旋转
48. 旋转图像
难点主要在于:
- 用翻转和镜像处理逆反和旋转,和逆转单词一样“难者不会,会者不难”,思路简单
- 镜像的坐标对应关系处理
- 语言特性的利用,不同语言有不同api,实际代码中会有很大不同,但思想一致
- 如果确定矩阵维数,通过线性代数应该可以直接计算答案...
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
//先行逆转
for(auto& row :matrix){
reverse(row.begin(),row.end());
}
int n=matrix[0].size();
//副对角线镜像
//matrix[i][j] <=> matrix[n-j-1][n-i-1]
//对角线上元素不用镜像,所以n-1
for(int i=0;i<n-1;i++){
for(int j=0;j<n-i-1;j++){
swap(matrix[i][j],matrix[n-j-1][n-i-1]);
}
}
}
};
螺旋矩阵
54. 螺旋矩阵
螺旋遍历其实也可以看作是一种迭代,每次遍历最外层,下一次遍历Matrix[m-1][n-1]的最外层,但实际执行时更重要的是遍历方向的处理,主要有两种思路:
- 一种有点像图形学中设置方向向量,在四种方向中碰壁后循环下一个方向向量
- 第二种就是不断迭代,每次迭代中处理四个方向,需要嵌套循环
最主要的就还是“碰壁”的判断,两种方法不一样,第一种设置访问矩阵确定是否是已访问数组,第二种则是边界判断
这里我直接贴第一种 模拟法 感觉比较有趣
class Solution {
private:
static constexpr int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return {};
}
int rows = matrix.size(), columns = matrix[0].size();
vector<vector<bool>> visited(rows, vector<bool>(columns));//访问标记数组
int total = rows * columns;//总路径长度
vector<int> order(total);//结果存储
int row = 0, column = 0;
int directionIndex = 0;
for (int i = 0; i < total; i++) {
//访问
order[i] = matrix[row][column];
visited[row][column] = true;
//计算前进方向
int nextRow = row + directions[directionIndex][0];
int nextColumn = column + directions[directionIndex][1];
//判断越界和重复访问
if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || nextColumn >= columns || visited[nextRow][nextColumn]) {
directionIndex = (directionIndex + 1) % 4;
}
row += directions[directionIndex][0];
column += directions[directionIndex][1];
}
return order;
}
};
本文来自博客园,作者:Alan-Blog,转载请注明原文链接:https://www.cnblogs.com/alanjiang/p/17607727.html