序文
Little KのLeetcode | Code Random Records | テーマ別コラムへようこそ、今日はスパイラルマトリックスをシェアします✨
59. スパイラルマトリックスⅡ
正の整数を指定するとn
、 1 から n 2までのすべての要素を時計回りの螺旋順序で含むn x n
正方行列を生成しますmatrix
。
例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
例 2:
输入:n = 1
输出:[[1]]
ヒント:
1 <= n <= 20
アイデア:
このタイプのトピックには実際にはアルゴリズムは含まれません。スパイラル順に印刷するプロセスをシミュレートするものです。以下でシミュレートしてみましょう。
- 上の行を左から右に埋めていきます
- 右の列を上から下まで埋めてください
- 降順の行を右から左に埋めていきます
- 左の列を下から上に埋めていきます
しかし、このようなシミュレーションの循環には多くの境界条件が存在し、間違いを犯しやすいことがわかります。このとき、最初のセクションで学んだ二分法で使用されるループ不変規則が非常に重要です。
マトリックスの 4 つの辺は、左が閉じて右が開いているか、左が開いていて右が閉じています。
class Solution {
public:
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>> res(n,vector<int>(n,0));
int startx=0,starty=0; //定义每循环一个圈的起始位置
int loop=n/2; //每个圈循环几次,如果n为奇数3,那么loop=1,只循环一圈
int mid=n/2; //矩阵中间位置,例如n为3,中间的位置为【1,1】
int count=1; //用来给矩阵元素赋值的
int offset=1; //用来控制循环遍历长度
int i,j;
while(loop--)
{
i=startx,j=starty;
//左闭右开
for(j=starty;j<starty+n-offset;j++) res[startx][j]=count++;
for(i=startx;i<startx+n-offset;i++) res[i][j]=count++;
for(;j>starty;j--) res[i][j]=count++;
for(;i>startx;i--) res[i][j]=count++;
//第二圈开始,起始位置要各自加一
startx++,starty++;
offset+=2;
}
//如果n为奇数,则需要单独给矩阵之间的位置赋值
if(n%2) res[mid][mid]=count;
return res;
}
};
シミュレーションのプロセスは上記のコードで詳しく説明されていますが、特に次の 2 つの点を説明します。
starty+n-offset
: 2 番目の円の開始座標が 0 ではないため、なぜここに開始位置が追加されるのかoffset+=2
: なぜ 2 を加えるかというと、一周するたびに両端の要素が欠落し、左閉じ右開きの原理に従って初期値が 1 になるためです。- 3 3 と 4 4 のシミュレーション図があります。
要約する
✨この種のトピックを実行するには、より多くのシミュレーションを描く必要がありますが、境界条件に注意を払って明確に考えるのは簡単です (ループ不変性のルールに従う)