この記事は、2021/08/12 に正式に開始された「LeetCode を征服する」シリーズ記事の 1 つです。LeetCode の一部の質問はロックされているため、このシリーズは、少なくともロックされていないすべての質問がクリアされるまで継続されます。LeetCode はまだ新しい質問を作成しているため、このシリーズの終了日は永遠になる可能性があります。この問題解決シリーズでは、さまざまな問題解決のアイデアとその最適化について説明するだけでなく、さまざまなプログラミング言語を使用して問題を解決する一般的な解決方法についてもまとめます。対応するアルゴリズム テンプレート。
PC 上でのコード ファイルの実行、デバッグ、共有を容易にするために、関連するウェアハウスも確立しました。このウェアハウスでは、元の LeetCode 質問へのリンク、解決策コード、解決策記事へのリンク、類似質問の概要、一般的な解決策の概要などだけでなく、元の質問の頻度などの重要な情報も確認できます。および関連会社。他に好ましい解決策がある場合は、他の人と共有できます。
この一連の記事の内容はいつでも更新および変更される可能性があるため、リマインダーとして「LeetCode を征服する」シリーズの記事の目次をフォローして保存しておいてください。
騎士はチェス盤n x n
を巡回します。効率的なパトロール計画では、ナイトはチェス盤の左上隅から開始し、チェス盤上の各マス目を正確に 1 回訪問します。
範囲内の異なる整数で構成される の整数行列が与えられます。 ここで、はn x n
、そのセルがナイトが訪問した番目のセルであることを表します。ナイトのアクションはインデックス0から始まります。grid
[0, n * n - 1]
grid[row][col]
(row, col)
grid[row][col]
grid
それが騎士の有効な巡回計画を表す場合はreturn true
、そうでない場合は return false
。
なお、騎士が行動すると、縦に2マス、横に1マス移動することも、横に2マス、縦に1マス移動することもできる。以下の図は、特定のグリッドから始まるナイトの 8 つの可能な行動ルートを示しています。
例 1:
输入:grid = [[0,11,16,5,20],[17,4,19,10,15],[12,1,8,21,6],[3,18,23,14,9],[24,13,2,7,22]]
输出:true
解释:grid 如上图所示,可以证明这是一个有效的巡视方案。
例 2:
输入:grid = [[0,3,6],[5,8,1],[2,7,4]]
输出:false
解释:grid 如上图所示,考虑到骑士第 7 次行动后的位置,第 8 次行动是无效的。
ヒント:
n == grid.length == grid[i].length
3 <= n <= 7
0 <= grid[row][col] < n * n
grid
内のすべての整数は互いに異なります
ソリューションダイレクトシミュレーション
この問題では、騎士の動きのすべてのステップが「太陽」の形に従ってジャンプする必要があります。位置(x 1, y 1) (x_1, y_1)から次のように仮定します。( ×1、y1) ( x 2 , y 2 ) (x_2, y_2)にジャンプします( ×2、y2)の場合、この時点で次の 2 つの状況のいずれかを満たす必要があります:
∣ x 1 − x 2 ∣ = 1 、∣ y 1 − y 2 ∣ = 2 |x_1 - x_2| = 1、|y_1 - y_2| = 2∣ x1−バツ2∣=1 、∣ y1−y2∣=2
行列の長さをnnとします。n,その中grid [ row ] [col ]grid[row][col]gr i d [ row ] [ co l ]はセル(行、列) (行、列)を表します。(行、_co l )は、騎士が訪問したグリッド [行] [列]gr i d [ row w ] [ co l ]セルなので、各セルのアクセス順序を知ることができます。インデックスインデックスを使用します。in dicesはセルのアクセス順序を格納します。ここで、indexs[i]はindexs[i]です。in di ces [ i ] は、ナイトが i 番目の i− 1 i-1私−1回ジャンプ後の位置
騎士の行動は添字0 0からなので0から始まるため、Grid [0] [0] = 0 Grid[0][0]=0 をグリッド[ 0 ] [ 0 ] _ _ _=0の場合、インデックスを各要素をサイコロで表します。インデックス [ i ]以降インデックス [i]in di ces [ i ]はジャンプの開始点です。indices [ i + 1 ] indices[i+1]in dice [ i _ _+1 ]がジャンプの終点であり、各ジャンプのアクション パスが「日」の形であるかどうか、つまり次の条件を満たすかどうかを確認します。
- ∣ インデックス [ i ] [ 0 ] − インデックス [ i + 1 ] [ 0 ] ∣ = 1 、 ∣ インデックス [ i ] [ 1 ] − インデックス [ i + 1 ] [ 1 ] ∣ = 2 ∣ |\textit{indices} [i][0] - \textit{インデックス}[i+1][0]| = 1, |\textit{インデックス}[i][1] - \textit{インデックス}[i+1][1]| = 2∣∣インデックス[ i ] [ 0 ]−インデックス[ i+1 ] [ 0 ] ∣=1 、∣インデックス[ i ] [ 1 ]−インデックス[ i+1 ] [ 1 ] ∣=2∣;
- ∣ インデックス [ i ] [ 0 ] − インデックス [ i + 1 ] [ 0 ] ∣ = 2 、 ∣ インデックス [ i ] [ 1 ] − インデックス [ i + 1 ] [ 1 ] ∣ = 1 ∣ |\textit{indices} [i][0] - \textit{インデックス}[i+1][0]| = 2、 |\textit{インデックス}[i][1] - \textit{インデックス}[i+1][1]| = 1∣∣インデックス[ i ] [ 0 ]−インデックス[ i+1 ] [ 0 ] ∣=2 、∣インデックス[ i ] [ 1 ]−インデックス[ i+1 ] [ 1 ] ∣=1∣。
計算を容易にするために、 ∣ x 1 − x 2 ∣ × ∣ y 1 − y 2 ∣ |x_1 - x_2| \times |y_1 - y_2| を検出するだけで済みます。∣ x1−バツ2∣×∣ y1−y2∣ 2 2に等しいか2で十分です。すべてのジャンプ パスが正当な場合は true を返します\text{true}true、それ以外の場合はfalse \text{false}偽。
class Solution {
public:
bool checkValidGrid(vector<vector<int>>& grid) {
if (grid[0][0] != 0) return false;
int n = grid.size();
vector<array<int, 2>> indices(n * n);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
indices[grid[i][j]] = {
i, j};
for (int i = 1; i < indices.size(); ++i) {
int dx = abs(indices[i][0] - indices[i - 1][0]);
int dy = abs(indices[i][1] - indices[i - 1][1]);
if (dx * dy != 2) return false;
}
return true;
}
};
複雑さの分析:
- 時間計算量: O ( n 2 ) O(n^2)O ( n2 )、ここでnnn は2 次元のチェス盤の辺の長さを表します。チェス盤上の各位置を検出する必要があり、合計n 2 n^2n位置が2 つあるため、時間計算量はO ( n 2 ) O(n^2) にO ( n2 )。
- 空間計算量: O ( n 2 ) O(n^2)O ( n2 )、ここでnnn は2 次元のチェス盤の辺の長さを表します。各場所のアクセス順序を格納するために使用され、n 2 n^2 個n2桁、必要なスペースはO ( n 2 ) O(n^2)O ( n2 )。