leetcode 54. スパイラルマトリックス
m
行と列 n
の行列が 与えられた場合 matrix
、 行列内のすべての要素を時計回りのスパイラル順に返してください。
Jianzhi Office の質問 29 に似ています。
アイデア: 円を時計回りにトラバースしているため、上、右、下、左からそれぞれトラバースします。1 つの円が完了したら、終了条件が満たされてループが停止するまで、次の円をトラバースします。このプロセスでは、値をトラバースしてコレクションに保存し、コレクションに返します。
一般的な考え方は上に示したとおりで、非常に単純ですが、この質問の難しさは次のとおりです。
1. 境界の値が正しいこと、および範囲外の配列がないことを確認します。
2. 各トラバース中に、左の閉じ、右の開き、または左の開きと右の閉じを均一に保つ必要があります。
3. 終了条件の判断、すべてのトラバースが完了するのはいつですか?
まず最初に、上、右、下、左という 4 つの変数を定義する必要があります。これらはそれぞれ、現在移動中の円の上、右、下、左の辺の位置を表します。円を移動するたびに、対応する変数が、左と右、または上と下に一致するまで、位置が減少します (ここで、左開きと右閉じ、または左閉じと右開きを実現することができます)。これは、各数値が通過されたことを意味し、これが終了条件です。
要約すると、コードは次のとおりです。
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> lists = new ArrayList<>();
int m = matrix.length ;//定义行数
int n = matrix[0].length ;//定义列数
//上下左右
//注意,这里的上下左右四个值,分别指的是遍历这一行或者这一列时,保持不动的那个行数或列数
//例如我们遍历第一行时,行数是up保持不变,列数是i进行递增
int up = 0;//遍历时的点坐标[up,i]
int right = n-1;//[i,right]
int down = m-1;//[down,i]
int left = 0;//[i,left]
while (true){
//从左到右
for (int i = left; i <= right; i++) {lists.add(matrix[up][i]);}
if (++up>down){break;}//每一行或者一列遍历完后,都要缩圈,这里是上边向下缩圈
//up已经完成加1操作,向下移动了一行,因为下面的从上到下遍历,是从up这一行开始的
//所以就实现了我们的右闭,后面的以此类推;
//当移动后的up与down冲突时,意味着遍历已经结束了,break跳出循环,下面的同理。
//从上到下
for (int i = up; i <= down; i++) {lists.add(matrix[i][right]);}
if (--right<left){break;}//右边遍历完,向左缩圈
//从右到左
for (int i = right; i >= left; i--) {lists.add(matrix[down][i]);}
if (--down<up){break;}//下边遍历完,向上缩圈
//从下到上
for (int i = down; i >= up; i--) {lists.add(matrix[i][left]);}
if (++left>right){break;}//左边遍历完,向右缩圈
}
return lists;
}