剑指Offer29.顺时针打印矩阵

题目:

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

示例一:

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

 示例二:

输入: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

 思路:

首先我们先来看题目,题目给出了几个提示:从外到里,顺时针。

根据这两个提示,我们就可以想到我们可以模拟这种状态,先将第一行,最后一列,最后一行,第一列看做一个整体,先输出它,然后再将这个整体向内缩小,这样就完成了对题目的模拟。具体如何操作看下面代码。

代码:

class Solution {
public:
    vector spiralOrder(vector>& matrix) {
        vector ans;
        if(matrix.size() == 0 || matrix[0].size() == 0) return ans;
        int left = 0;
        int right = matrix[0].size() - 1;
        int top = 0;
        int bottom = matrix.size() - 1;
        while(left <= right && top <= bottom){
            for(int column = left; column <= right; column ++){//第一行
                ans.push_back(matrix[top][column]);
            }
            for(int row = top + 1; row <= bottom; row ++){//倒数第一列
                ans.push_back(matrix[row][right]);
            }
            if(left < right && top < bottom){
                for(int column = right - 1; column > left; column--){//倒数第一行
                    ans.push_back(matrix[bottom][column]);
                }
                for(int row = bottom; row > top; row --){//第一列
                    ans.push_back(matrix[row][left]);
                }
            }
            left++;
            right--;
            top++;
            bottom--;
        }
        return ans;
    }
};

        vector ans;

        if(matrix.size() == 0 || matrix[0].size() == 0) return ans;

 首先ans数组为我们按照题目创建的结果数组,下面的if判断就是为了当给定的数组为空时,直接返回我们刚创建的空数组(题目要求中给出了数组大小可以为0,所以我们要有这步)。

        int left = 0;

        int right = matrix[0].size() - 1;

        int top = 0;

        int bottom = matrix.size() - 1;

这些就是我们再下面进行模拟时需要用到的变量,因为我们要涉及到思路中说到的整体的缩小,所以我们需要去使用变量来控制。

left和right就分别是左边界和有边界,top和bottom分别是上边界和下边界。

        while(left <= right && top <= bottom){

            for(int column = left; column <= right; column ++){//第一行

                ans.push_back(matrix[top][column]);

            }

            for(int row = top + 1; row <= bottom; row ++){//倒数第一列

                ans.push_back(matrix[row][right]);

            }

            if(left < right && top < bottom){

                for(int column = right - 1; column > left; column--){//倒数第一行

                    ans.push_back(matrix[bottom][column]);

                }

                for(int row = bottom; row > top; row --){//第一列

                    ans.push_back(matrix[row][left]);

                }

            }

            left++;

            right--;

            top++;

            bottom--;

        }

 

下面这些就是我们对于顺时针输出的模拟,首先输出第一行,也就是第一个for循环,column就是列数,我们要输出的就是行数为top的并且列数在left到right的值。

接下来输出的就是倒数第一列,也就是第二个for循环,row就是行数,我们要输出的是列数为right并且行数在top+1(因为top那一行我们已经输出过最后一个数了,所以此时加一)到bottom的值。

后面的if(left < right && top < bottom)是因为当我们进行到最里层的时候,有可能只剩一行两个元素或者一列两个元素或只剩一个元素时,left = right, top = bottom 会导致我们重复输出一个数,最终导致出错,所以我们在这里进行了一个判断。

第三次输出的就是倒数第一行了,我们要倒着输出(column--)的就是行数为bottom并且列数在right - 1(这里减一的原因和之前top+1的原因一样,都是因为输出过了)到left(不包括left,为了下面输出第一列时服务,这样我们就能直接从bottom开始输出)的值。

第四次输出的就是第一列的值,我们要倒着输出(row--)的就是列数为left并且行数在bottom到top(不包括top,因为这个位置输出第一行时输出过了)的值。

接下来就是我们要进行整体的缩小了,也就是操作各个边界,上边界(top)和左边界(left)++,下边界(bottom)和右边界(right)--;

时间复杂度:O(n*m)

        注:n和矩阵的行数,m为矩阵的列数

空间复杂度:O(1)

你可能感兴趣的:(矩阵,线性代数)