《剑指offer》 面试题29. 顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

限制:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100

按路径模拟

仔细研究下矩阵,会发现就顺时针按固定的四个方向。因此抓住这一点就能解决

可以模拟打印矩阵的路径。初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前访问过的位置时,则顺时针旋转,进入下一个方向。

判断路径是否进入之前访问过的位置需要使用一个与输入矩阵大小相同的辅助矩阵 visited,其中的每个元素表示该位置是否被访问过。当一个元素被访问时,将 visited 中的对应位置的元素设为已访问。

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return {};
        }
        int len_x = matrix.size();
        int len_y = matrix[0].size();
        vector<int> res(len_x*len_y);
        vector<vector<bool>> vis(len_x, vector(len_y, false));
        int next[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int duration = 0;
        int x = 0;
        int y = 0;
        res[0] = matrix[x][y];
        vis[x][y] = true;
        for(int i = 1; i < len_x*len_y; i++){
            int tx = x + next[duration][0];
            int ty = y + next[duration][1];
            
            if(tx < 0 || tx >= len_x || ty < 0 || ty >= len_y || vis[tx][ty]){
                duration = (duration+1)%4;
                tx = x + next[duration][0];
                ty = y + next[duration][1];
            }

            vis[tx][ty] = true;
            res[i] = matrix[tx][ty];
            x = tx;
            y = ty;
        }
        return res;
    }
};

按层模拟

将矩阵看成若干层,首先打印最外层的元素,其次打印次外层的元素,直到打印最内层的元素。

对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于(top,left),右下角位于 (bottom,right),按照如下顺序遍历当前层的元素。

  1. 从左到右遍历上侧元素,依次为(top,left) 到 (top,right)。
  2. 从上到下遍历右侧元素,依次为 (top+1,right) 到(bottom,right)。
  3. 如果left<right 且 top<bottom,则从右到左遍历下侧元素,依次为 (bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到 (top+1,left)。

遍历完当前层的元素之后,将 left 和op 分别增加 1,将 right 和 bottom 分别减少 1,进入下一层继续遍历,直到遍历完所有元素为止。
在这里插入图片描述

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty())	return {};
        int top   = 0;
        int bot   = matrix.size() - 1;
        int left  = 0;
        int right = matrix[0].size() - 1;
        vector<int> result(matrix.size() * matrix[0].size());
        int index = 0;
        while (top <= bot && left <= right)
        {
            for (int i = left; i <= right; ++i){
                result[index++] = matrix[top][i];
            }
            ++top;
            if (top > bot)	break;
            for (int i = top; i <= bot; ++i){
                result[index++]= matrix[i][right];
            }
            --right;
            if (left > right)	break;
            for (int i = right; i >= left; --i){
                result[index++]= matrix[bot][i];
            }
            --bot;
            if (top > bot)	break;
            for (int i = bot; i >= top; --i){
                result[index++] = matrix[i][left];
            }
            ++left;
        }
        return result;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章