解法一:遇到障碍就停
此法需要建一个表来表示是否遍历过这个点。会有额外的空间复杂度,但是写起来比较简单。这里用了set是为了省事,实际用二维数组比较好。
class Solution {
public:
int violate(pair<int, int> p, int M, int N)
{
if(p.first >= 0 && p.first < M && p.second >= 0 && p.second < N)return 0;
return 1;
}
vector<int> spiralOrder(vector<vector<int>>& matrix) {
if(matrix.size() == 0 || matrix[0].size() == 0)return vector<int>{};
vector<int> v{matrix[0][0]};
set<pair<int, int>> traversed{pair(0, 0)};
// 方向:右,下,左,上
vector<pair<int, int>> D{pair(0, 1), pair(1, 0), pair(0, -1), pair(-1, 0)};
int d, r, c;
d = r = c = 0;
int M = matrix.size(), N = matrix[0].size();
while(1)
{
if(traversed.size() == M*N)return v;
pair<int, int> p(r+D[d].first, c+D[d].second);
if(traversed.count(p) || violate(p, M, N))
{
d = (d+1)%4;
}
r += D[d].first;
c += D[d].second;
traversed.insert(pair(r, c));
v.push_back(matrix[r][c]);
}
}
};
解法二:记录边界,O(1)空间
这里的样例给的是螺旋数组2的,题目其实一样。上图中的代码十分简洁,若想省下多余的空间,需要对四种情况分开判断,想明白这一点,不怕麻烦,题目就很简单了。
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> ret(n, vector<int>(n, 0));
vector<int> most{n-1, n-1, 0, 1};
int i = 0, j = 0, ct = 1;
while(ct <= n*n)
{
while(j<=most[0])ret[i][j++] = ct++;
j -= 1;
i += 1;
most[0] -= 1;
while(i<=most[1])ret[i++][j] = ct++;
i -= 1;
j -= 1;
most[1] -= 1;
while(j>=most[2])ret[i][j--] = ct++;
j += 1;
i -= 1;
most[2] += 1;
while(i>=most[3])ret[i--][j] = ct++;
i += 1;
j += 1;
most[3] += 1;
}
return ret;
}
};