二维数组花式遍历(旋转,螺旋) [labuladong-刷题打卡 day5]

发布时间 2023-08-05 11:46:12作者: Alan-Blog

矩阵旋转

48. 旋转图像
难点主要在于:

  1. 用翻转和镜像处理逆反和旋转,和逆转单词一样“难者不会,会者不难”,思路简单
  2. 镜像的坐标对应关系处理
  3. 语言特性的利用,不同语言有不同api,实际代码中会有很大不同,但思想一致
  4. 如果确定矩阵维数,通过线性代数应该可以直接计算答案...
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]的最外层,但实际执行时更重要的是遍历方向的处理,主要有两种思路:

  1. 一种有点像图形学中设置方向向量,在四种方向中碰壁后循环下一个方向向量
  2. 第二种就是不断迭代,每次迭代中处理四个方向,需要嵌套循环
    最主要的就还是“碰壁”的判断,两种方法不一样,第一种设置访问矩阵确定是否是已访问数组,第二种则是边界判断
    这里我直接贴第一种 模拟法 感觉比较有趣
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;
    }
};