leetcode之Spiral Matrix 和Spiral Matrix II

来源:互联网 发布:手机归属地数据库 编辑:程序博客网 时间:2024/04/29 08:52

第一题的原题如下:

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].

第二题的原题如下:

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:
[ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ]]

首先说第一题的思路:

由于受之前顺时针反转90度的影响,所以我首先想到的是从外圈向内循环,首先是圈数的确定,然后是四个边的依次循环,这种思路能够通过大多数的测试用例,但3行4列时会重复输出最后一个元素,最后加了限制条件后测试通过,代码如下:

class Solution {public:    vector<int> spiralOrder(vector<vector<int> > &matrix) {        vector<int>v;if(matrix.size() == 0)return v;if(matrix[0].size() == 0)return v;int m = matrix.size();int n = matrix[0].size();if(m == 1){v = matrix[0];return v;}if( n == 1){for(int i = 0; i < m; i++){v.push_back(matrix[i][0]);}return v;}int min = m < n ? m:n;if(min % 2 == 0)     min = min / 2;elsemin = min /2 +1;for(int i = 0; i < min; i++){//从外到内的圈数int t = i;//top行for(t = i; t < n - i; t++){ //行不变列变v.push_back(matrix[i][t]);  }t--;int r = i;  //right列for(r = i + 1; r < m - i; r++){  //列不变行变v.push_back(matrix[r][t]);}r--;int b = t; //bottom行for(b = t -1; b >= i;b--){  //行不变列变    if(r != i || b != i)    v.push_back(matrix[r][b]);}b++;int l = r;//left列for(l = r - 1; l > i; l--){  //列不变行变v.push_back(matrix[l][b]);}}return v;    }};

从上述代码可以看出,在遍历bottom行时多了一个判断条件,这就是为了防止多打印最后一个数字所加的,从这道题我深切的感受到bug的不可避免性!

由于上述代码第3个小循环需要加条件限制,而这在测试前是不容易发现的,所以又在上述基础上找到了一种改进的算法,其思路是首先记录上下左右四个边界,然后上下左右依次循环,每次循环减少一个边界值,当有两个边界值重合时(上下重合或者左右重合)遍历结束,该方法不存在多打印最后一个元素的问题,而且思路也比较清晰,代码如下:

class Solution {public:    vector<int> spiralOrder(vector<vector<int> > &matrix) {      vector<int>v;if(matrix.size() == 0)return v;if(matrix[0].size() == 0)return v;int m = matrix.size();int n = matrix[0].size();if(m == 1){v = matrix[0];return v;}if( n == 1){for(int i = 0; i < m; i++){v.push_back(matrix[i][0]);}return v;}int xMin = 0,yMin = 0;//待遍历的行和列int xMax = matrix.size();//已经遍历的行int yMax = matrix[0].size();已经遍历的列int i = 0, j = 0;while (true){while( j < yMax)v.push_back(matrix[i][j++]);if(++xMin >= xMax)//待遍历等于已遍历时,循环结束break;i++;j--;while(i < xMax)v.push_back(matrix[i++][j]);if(--yMax <= yMin)break;i--;j--;while(j >= yMin)v.push_back(matrix[i][j--]);if(--xMax <= xMin)break;i--;j++;while(i >= xMin)v.push_back(matrix[i--][j]);if(++yMin >= yMax)break;i++;j++;}return v;    }};
在上述代码中,注意要小于上限而大于等于下限,另外要注意是i++和i--的区别。

在第一题做出来后,第二题的思路也就不难了,仍采用上述第二种方法,代码如下:

class Solution {public:    vector<vector<int> > generateMatrix(int n) {        vector<vector<int>>vv;if(n == 0)return vv;vector<int>v(n);for(int i = 0; i < n; i++){vv.push_back(v);}int xMin = 0,yMin = 0;int xMax = n;int yMax = n;int i = 0, j = 0;int k = 1;while(true){while(j < yMax){vv[i][j++] = k++;}if(++xMin >= xMax)break;j--;i++;while(i < xMax){vv[i++][j] = k++;}if(--yMax <= yMin)break;i--;j--;while (j >= yMin){vv[i][j--] = k++;}if(--xMax <= xMin)break;i--;j++;while(i >= xMin){vv[i--][j] = k++;}if(++yMin >= yMax)break;i++;j++;}return vv;    }};
这里仍要注意的是上下限的判断问题,我在编码过程中就因为将>=写成了>,导致找了半天的bug,一定要认真再认真啊!



0 0
原创粉丝点击