29. 顺时针打印矩阵

https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/

directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};这个是第二次遇到了,但还是不熟练,用二维数组表示遍历的方向

class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        if(matrix.size()==0)    return {};
        //保存矩阵的长和宽
        int len = matrix[0].size();
        int kuan = matrix.size();
        //顺时针打印的方向永远都是右、下、左、上四个方向
        vector directions = { 0,1,2,3 };
        //使用for循环不太好用,试试while循环,循环结束的条件就是输出的数据
        //达到len*kuan
        vector num;
        int dir = 0;
        //保存初始的遍历下标
        int i = 0;
        int j = 0;
        while (len * kuan != num.size()) {
            //表示向右
            if (directions[dir] == 0) {
                for (; j < len; j++) {
                    if (matrix[i][j] == -100)
                        break;
                    num.push_back(matrix[i][j]);
                    matrix[i][j] = -100;
                }
                j = j - 1;
                i = i + 1;
            }
            //表示向下
            else if (directions[dir] == 1) {
                for (; i < kuan; i++) {
                    if (matrix[i][j] == -100)
                        break;
                    num.push_back(matrix[i][j]);
                    matrix[i][j] = -100;
                }
                i = i - 1;
                j = j - 1;
            }
            //向左
            else if (directions[dir] == 2) {
                for (; j >= 0; j--) {
                    if (matrix[i][j] == -100)
                        break;
                    num.push_back(matrix[i][j]);
                    matrix[i][j] = -100;
                }
                j = j + 1;
                i = i - 1;
            }
            //向上
            else if (directions[dir] == 3) {
                for (; i >= 0; i--) {
                    if (matrix[i][j] == -100)
                        break;
                    num.push_back(matrix[i][j]);
                    matrix[i][j] = -100;
                }
                i = i + 1;
                j = j + 1;
            }
            dir=(dir+1)%4;
        }
        return num;
    }
};

这是我自己写的思路,时间复杂度未O(n*m),一次遍历循环输出。其中判断是否访问过,我用的方法就是将其中的元素置为-100,但正确的应该是用一个辅助数组来判断,或者用hashmap判断

class Solution {
private:
    //表示四个方向:右、下、上、左
    static constexpr int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public:
    vector spiralOrder(vector>& matrix) {
        //特殊判断
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }
        //行列
        int rows = matrix.size(), columns = matrix[0].size();
        //辅助数组判断是否访问过
        vector> visited(rows, vector(columns));
        //总的数据个数
        int total = rows * columns;
        //返回值
        vector 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], 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;
    }
};

这个是优化之后的,使用一个数组来保存其中四个方向,遍历的时候判断下一次的位置是否越界以及是否访问过,是则改变方向,方向也是从右、下、左、上的。

一下是官方题解的另一种思路:https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/solution/shun-shi-zhen-da-yin-ju-zhen-by-leetcode-solution/

29. 顺时针打印矩阵_第1张图片
29. 顺时针打印矩阵_第2张图片
29. 顺时针打印矩阵_第3张图片
class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }

        int rows = matrix.size(), columns = matrix[0].size();
        vector order;
        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;
    }
};

K神的题解和上面的按层遍历差不多,但是理解的方式不同,就是判断输出完毕的方式不同,而且代码更加简洁

29. 顺时针打印矩阵_第4张图片
29. 顺时针打印矩阵_第5张图片
class Solution 
{
public:
    vector spiralOrder(vector>& matrix) 
    {
        if (matrix.empty()) return {};
        vector res;
        int l = 0;                      //左边界
        int r = matrix[0].size() - 1;   //右边界
        int t = 0;                      //上边界
        int b = matrix.size() - 1;      //下边界
        while (true)
        {
            //left -> right
            for (int i = l; i <= r; i++) res.push_back(matrix[t][i]);
            // 上边界下移,如果超出下边界则退出
            if (++t > b) break;
            //top -> bottom
            for (int i = t; i <= b; i++) res.push_back(matrix[i][r]);
             // 右边界左移,如果超出左边界则退出
            if (--r < l) break;
            //right -> left
            for (int i = r; i >= l; i--) res.push_back(matrix[b][i]);
            // 下边界上移
            if (--b < t) break;
            //bottom -> top
            for (int i = b; i >= t; i--) res.push_back(matrix[i][l]);
            if (++l > r) break;
        }
        return res;
    }
};

你可能感兴趣的:(剑指offer刷题,算法)