这道题我戏称为“迷宫题”。回忆一下小时候在公园里,是否遇到过这样一种简陋迷宫,迷宫里不断的转圈,最终你进入了一个圆圈的中心,可能有个小广场,小雕塑,或是小房子在那里等着你。

这道题只不过把圈圈变成了正方形罢了。处于中心位置的数,恰好是 n*n.


不知道上述的描述会不会给你什么启发,而我就是完全依照这个思路去解的,所以效率也许并不高,也说不出这属于那种算法的范畴。以三维矩阵为例,设行为i, 列为j,如果把最外圈转一遍,记录步骤如下表:

i j 条件 动作
0 0 i==0 && j!=n-1 ++j
0 1 i==0 && j!=n-1 ++j
0 2 i==0 && j!=n-1 ++j
1 2 j==n-1 && i!=n-1 ++i
2 2 j==n-1 && i!=n-1 ++i
2 1 i==n-1 && j!=0 –j
2 0 i==n-1 && j!=0 –j
1 0 j==0 && i!=0 –i
0 0 j==0 && i!=0 –i

可以发现,最后我们又回到了原点,却没有像我们想象的那样,停在[1][0]的地方,在迷宫里,这个地方意味着你面对着一堵墙,你不能去撞墙,而是要右转进入下一个圈圈。

程序里,我们就要为墙所在的地方设置标记位。换句话说,我们也可以给不为墙的地方设置标记位,如给二维数组初始化时,将值设为 -1.那么走过的地方自然不可能为 -1,就成了墙。

所以转圈停止的条件为: Matrix[i][j] != -1;

ok,如果将每一步产生的值记录下来(设为value, 每走一步就自加), 那么当 value == nn 的时候就算走到了中心。如果不等于 nn,就要向里面再转一圈。

思路很清楚了,我觉得这个解法很直接,代码也并不繁复,非常好理解。请大家拍砖。

#include <vector>
using std::vector;

class Solution {
public:
    vector<vector<int> > generateMatrix(int n) {
        vector<vector<int>> vec(n, vector<int>(n,-1));
        for (int i=0, j=n; value != n*n; ++i, --j)
            spiralFilled(i, j, vec);
        return vec;
    }
private:
    void spiralFilled(int beg, int end, vector<vector<int> >& vec)
    {
        for (int i=beg, j=beg; true; )
        {
            if (vec[i][j] == -1) vec[i][j] = ++value;
            else break;
            if (i == beg && j != end-1) { ++j; continue; }
            if (j == end-1 && i != end-1) { ++i; continue; }
            if (i == end-1 && j != beg) { --j; continue; }
            if (j == beg && i != beg) { --i; continue; }
        }
    }
    
    int value{0};
};

LeetCode Direct Link