三种方法遍历螺旋数组(dfs四个方向模拟层层模拟)

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三种方法遍历螺旋数组(dfs四个方向模拟层层模拟)相关的知识,希望对你有一定的参考价值。

题目

在这里插入图片描述

dfs解决

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        m = matrix.size()-1;
        n = matrix[0].size()-1;
        dfs(matrix,0,0);
        return res;
    }
private:
    int m;
    int n;
    //用于记录遍历的是第几个圈
    int count = 0;
    vector<int>res;
    void dfs(vector<vector<int>>& matrix,int i,int j){
        //用于终止条件
        if(res.size()==matrix.size()*matrix[0].size())
            return;
        //遍历上方一横条
        if(j<n-count&&i==count){
            res.push_back(matrix[i][j]);
            dfs(matrix,i,j+1);
        }//遍历右边一竖条
        else if(j==n-count&&i<m-count){
            res.push_back(matrix[i][j]);
            dfs(matrix,i+1,j);
        }//遍历下方一横条
        else if(i==m-count&&j-count>0){
            res.push_back(matrix[i][j]);
            dfs(matrix,i,j-1);
        }//遍历左边一竖条,并且进行特殊判断(当遍历到左边一竖条的最后一个元素的时候需要换一圈进行遍历(故此时更新count并换情况dfs下一层))
        else if(j==count&&i-count>0){
            res.push_back(matrix[i][j]);
            if(j==count&&i-count==1){
                count++;
                dfs(matrix,i,j+1);
            }else
            dfs(matrix,i-1,j);
        }else{
            //用于处理特殊情况:当遍历不是环形,而是只有一层的时候会把最后一个元素漏掉
            res.push_back(matrix[i][j]);
        }
    }
};

从外到内层层模拟

class Solution {
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<int> order;
        //left right用于记录每层的左右边界,top和bottom用于记录每层的上下边界
        int left = 0, right = columns - 1, top = 0, bottom = rows - 1;
        while (left <= right && top <= bottom) {
            //遍历每层的时候不要改变各层边界的指标,在最后才进行改变,表示进入到下一层进行遍历

            //遍历上面的横向
            for (int column = left; column <= right; column++) {
                order.push_back(matrix[top][column]);
            }//遍历右边的竖向
            for (int row = top + 1; row <= bottom; row++) {
                order.push_back(matrix[row][right]);
            }//根据判断情况看是否需要遍历左边和下面的竖向和横向
            if (left < right && top < bottom) {
                for (int column = right - 1; column > left; column--) {
                    order.push_back(matrix[bottom][column]);
                }
                for (int row = bottom; row > top; row--) {
                    order.push_back(matrix[row][left]);
                }
            }
            //更新每层的相关信息
            left++;
            right--;
            top++;
            bottom--;
        }
        return order;
    }
};

依靠四个方向模拟

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;
        //用于确定下一个遍历方向的标记,可以通过对4取模得到四种遍历方向的连续变化。
        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], 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;
    }
};

以上是关于三种方法遍历螺旋数组(dfs四个方向模拟层层模拟)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode54. 螺旋矩阵

leetcode 54 螺旋数组

ACM之螺旋矩阵

控制遍历方向模拟题--Z字形变换

59. 螺旋矩阵 II-内环模拟遍历

回顾:螺旋打印数组