LeetCode(54) SpiralMatrix

来源:互联网 发布:linux kernel启动参数 编辑:程序博客网 时间:2024/06/13 02:55

题目如下:

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
For example,
Given the following matrix:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
You should return [1,2,3,6,9,8,7,4,5].

分析如下:

题目的意思是,按照顺时针方向旋转着遍历矩阵,把遍历结果返回。关键是怎么理解旋转的含义?

可以这样来思考。以上面的矩阵为例。

step one: 1,2

step two: 3,6

step three: 9,8

step four: 7,4

这样完成了对最外层的遍历,剥去一层之后(leetcode官网上说,想象剥洋葱那样剥去一层),继续往下剥,去掉次外层,不断进行下去,直到边界条件。显然边界条件是最后只剩1个点,或者一行,或者一列,导致没法拐个弯形成一个矩形。

那么边界条件是什么时候可能发生呢?这是本题最坑爹的地方了,我在这里写了很久才找到正确的边界条件判断语句。

需要写几个4*4, 4*6, 4*2, 5*5, 5*3, 5*7, 4*5, 4*3, 5*4, 5*6例子自己看看,这样才能看出来。


结合看上面的图,可以知道,

1 在rowcount 和colcount中选较小值。到底剥洋葱剥了几层由较小值决定。

2 如果较小值是奇数,那么剥洋葱到最后会产生一条单独的线段。如果较小值是偶数,然么剥洋葱到最后就会完成所有点的打印,不会留有单独的线段。


上面的做法是顺着题意思考的做法,思考边界条件的地方非常坑爹。

还有一种做法是递归,参见leetcode官网的解释,代码量顿时减少很多,虽然时间慢一些,但是本题的递归并没产生太多重复的计算,所以时间空间的开销都是可以忍的。

我的代码:

// 4ms过大集合class Solution {public:    vector<int> spiralOrder(vector<vector<int> > &matrix) {        vector<int> res;        int row=(int)matrix.size();        if(row==0)            return res;        int col=(int)matrix[0].size();        if(col==0)            return res;        int count=row<col?row:col;        for(int i=0;i<count/2;i++){            for(int j=i;j<col-1-i;j++)                res.push_back(matrix[i][j]);            for(int j=i;j<row-1-i;j++)                res.push_back(matrix[j][col-i-1]);            for(int j=col-1-i;j>i;j--)                res.push_back(matrix[row-1-i][j]);            for(int j=row-1-i;j>i;j--)                res.push_back(matrix[j][i]);        }        //单独处理在最后可能出现的单列或者单行的情况        if(row%2==1&&col%2==1){ //行数为奇,列数为奇,必然需要处理单行或单列            if(row<=col){                for(int i=0;i<=col-row;i++)                    res.push_back(matrix[row/2][row/2+i]);            }else{                for(int i=0;i<=row-col;i++)                    res.push_back(matrix[col/2+i][col/2]);            }        }else if(row%2==1&&col%2==0){ //行数为奇,列数为偶,仅当row<col才需要处理单行或单列            if(row<col){                for(int i=0;i<=col-row;i++)                    res.push_back(matrix[row/2][row/2+i]);            }        }else if(row%2==0&&col%2==1){//行数为偶,列数为奇,仅当col<row才需要处理单行或单列            if(col<row){                for(int i=0;i<=row-col;i++)                    res.push_back(matrix[col/2+i][col/2]);            }        }        return res;   }};

//leetcode官网解答void print_spiral(int mat[][N_MAX], int m, int n, int k) {  if (m <= 0 || n <= 0)    return;  if (m == 1) {    for (int j = 0; j < n; j++)      cout << mat[k][k+j] << " ";    return;  }  if (n == 1) {    for (int i = 0; i < m; i++)      cout << mat[k+i][k] << " ";    return;  }  // print from top left  for (int j = 0; j < n - 1; j++)    cout << mat[k][k+j] << " ";  // print from top right  for (int i = 0; i < m - 1; i++)    cout << mat[k+i][k+n-1] << " ";  // print from bottom right  for (int j = 0; j < n - 1; j++)    cout << mat[k+m-1][k+n-1-j] << " ";  // print from bottom left  for (int i = 0; i < m - 1; i++)    cout << mat[k+m-1-i][k] << " ";   print_spiral(mat, m-2, n-2, k+1);} void print_spiral_helper(int mat[][N_MAX], int m, int n) {  print_spiral(mat, m, n, 0);}

题目小结:

(1) 这道题写了很久才写出来。首先是没有想到用递归,如果用递归,可以很快写出来。其次是,就算没有想到用递归,那么迭代版依然花了很长时间,这里面的时间大量花费在没有真正想清楚边界条件就去着急写code了。所以如果没有想清楚,不要着急写。最省时间的方式是先想清楚了再写。


update: 2015-01-10

//4ms class Solution {public:    vector<int> spiralOrder(vector<vector<int> > &matrix) {        vector<int> res;        int nRow = matrix.size();        if (nRow == 0) return res;        int nCol = matrix[0].size();        if (nCol == 0) return res;        if (nRow == 1) return matrix[0];        if (nCol == 1) {            for (int i = 0; i < nRow; ++i)                res.push_back(matrix[i][0]);            return res;        }                int offset_range = nRow < nCol ? nRow/2 : nCol/2;        for (int offset = 0; offset < offset_range; ++offset) {                        // up            for (int i = offset; i < nCol - offset - 1; ++i) {                res.push_back(matrix[offset][i]);            }                    // right            for (int i = offset; i < nRow - offset - 1; ++i) {                res.push_back(matrix[i][nCol - offset - 1]);            }                    //down            for (int i = nCol - offset - 1; i >= 1 + offset; --i) {                res.push_back(matrix[nRow - offset - 1][i]);            }                            //left            for (int i = nRow - offset - 1; i >= 1 + offset; --i) {                res.push_back(matrix[i][offset]);            }                }                if (nRow < nCol && nRow % 2 == 1) {            for (int i = offset_range; i < nCol - offset_range; ++i ) {                res.push_back(matrix[nRow/2][i]);            }        } else if (nRow >= nCol && nCol %2 == 1) {            for (int i = offset_range; i < nRow - offset_range; ++i) {                res.push_back(matrix[i][nCol/2]);            }        }                return res;    }};

这道题目还有续集 Spiral Matrix II,其实本质是同一道题目。

0 0
原创粉丝点击