この記事はWeChatの公開アカウント「labuladong」から転載したもので、著者はlabuladongです。この記事を転載する場合は、labuladong の公開アカウントにご連絡ください。 島問題は、面接でよく聞かれる古典的な質問です。基本的な島問題は難しくありませんが、サブ島の数や異なる形状の島の数を求めるなど、島問題には興味深い拡張がいくつかあります。この記事では、これらすべての問題を一挙に取り上げます。 島系列問題の核心は、DFS/BFS アルゴリズムを使用して 2 次元配列を走査することです。 この記事では主に、DFS アルゴリズムを使用して島系列問題を数秒で解決する方法について説明します。ただし、BFS アルゴリズムを使用するという中核的な考え方はまったく同じです。DFS を BFS に書き換えるだけです。 では、2 次元マトリックスで DFS 検索を使用するにはどうすればよいでしょうか。2 次元マトリックス内の各位置をノードと見なし、このノードの上下左右の 4 つの位置を隣接ノードと見なすと、マトリックス全体をメッシュのような「グラフ」構造に抽象化できます。 データ構造とアルゴリズムを学習するフレームワーク思考によれば、バイナリツリーのトラバーサルフレームワークに基づいて、2次元行列の DFS コードフレームワークを書き直すことは完全に可能です。
2次元行列は本質的に「グラフ」であるため、トラバーサルプロセス中に後戻りを防ぐために、訪問済みのブール配列が必要です。上記のコードを理解できれば、すべての島の問題は簡単に解決できます。 2 次元配列を処理するための追加のトリックを次に示します。上、下、左、右のトラバーサルを処理するために「方向配列」が使用されることがありますが、これは前の記事のグラフ トラバーサル フレームワークのコードと非常によく似ています。
この書き方は、for ループを使用して上下左右のトラバースを処理するだけです。 書き方は個人の好みに応じて選択できます。 島の数これは、最も単純で最も古典的な島の問題であるパズル「島の数」の200番目の質問です。 質問では、0または1のみを含む2次元配列グリッドを入力する必要があります。0は海水を表し、1は陸地を表し、マトリックスはすべての側面が海水に囲まれていると想定されます。 陸地がつながって島を形成すると言われているので、このマトリックス グリッド内の島の数を計算するアルゴリズムを記述してください。関数のシグネチャは次のとおりです。
たとえば、質問で 4 つの島がある次のグリッドが与えられた場合、アルゴリズムは 4 を返す必要があります。 アイデアは非常にシンプルです。鍵となるのは、「島」を見つけてマークする方法です。ここで DFS アルゴリズムが役立ちます。ソリューション コードを直接見てみましょう。
なぜ、島に遭遇するたびに DFS アルゴリズムを使用して島を「洪水」させるのでしょうか。これは主に、トラブルを回避し、訪問した配列の維持を回避するためです。 dfs 関数は、値が 0 の位置に移動すると直接戻るため、渡されたすべての位置が 0 に設定されている限り、戻りません。 PS: このタイプの DFS アルゴリズムは、FloodFill アルゴリズムとも呼ばれます。FloodFill という名前は適切だと思いますか? この最も基本的な島の問題について私たちが言うべきことはこれだけです。次にどんな話題が出てくるか見てみましょう。 閉鎖された島の数前回の質問では、2次元マトリックスは海水に囲まれていると考えられるため、端に近い陸地も島とみなされると述べていました。 問題 1254「閉じた島の数を数える」は、次の 2 つの点で前の問題と異なります。 1. 陸地を表すには 0 を使用し、海水を表すには 1 を使用します。 2. 「閉じた島」の数を計算してみましょう。いわゆる「閉じた島」とは、四方を 1 で囲まれた 0 のことです。つまり、端に近い土地は「閉じた島」とはみなされません。 関数のシグネチャは次のとおりです。
たとえば、質問では次の 2 次元行列が入力として与えられます。 アルゴリズムは 2 を返し、画像内の灰色の 0 のみが海水に囲まれた「閉じた島」です。 では、「閉じた島」をどのように特定するのでしょうか。実はとても簡単です。前の質問で端に近い島を除外すると、残ったものが「閉じた島」になるんですよね? この考えを念頭に置いて、コードを直接見てみましょう。この質問では、0 は陸地を表し、1 は海水を表すと規定されていることに注意してください。
事前に付近の陸地が浸水していれば、島は閉鎖島として計算できます。 PS: DFS/BFS アルゴリズムに加えて、Union Find アルゴリズムもこのタイプのアイランド問題に対処するためのオプションの方法です。前回の記事の Union Find アルゴリズムは、同様の問題を解決するために使用されました。 この島の問題の解決法を少し変更すると、質問 1020 の「飛び地の数」の問題を解くことができます。この問題では、閉じた島の数を求めるのではなく、閉じた島の合計面積を求めます。 実際、考え方は同じです。まず、端に近い土地を水没させ、次に残りの土地を数えます。質問 1020 では、1 は土地、0 は海水を表すことに注意してください。
スペースの制限により、具体的なコードは書きません。引き続き他の島の問題を見てみましょう。 島の最大の面積これはゲーム「島の最大面積」の695番目の質問です。0は海水を表し、1は陸を表します。ここでは島の数を数えるのではなく、最大の島の面積を計算します。関数のシグネチャは次のとおりです。
たとえば、質問では次の 2 次元行列が入力として与えられます。 最大の島はオレンジ色の島で、アルゴリズムはその面積を 6 として返します。 この問題の基本的な考え方は、dfs 関数が島を洪水させる一方で、島の面積を記録する方法も見つける必要があることを除いて、前の問題とまったく同じです。 dfs 関数の戻り値を設定すると、毎回浸水した土地の数を記録できます。解決策を直接見てみましょう。
解決策は前のものと似ているので、あまり説明しません。次の 2 つの島の問題はより技術的なので、詳しく見ていきましょう。 サブアイランドの数前の質問がテンプレート質問である場合、質問 1905「サブアイランドの数え方」を解くには頭を使う必要があるかもしれません。 この質問の鍵は、サブアイランドをいかに素早く特定するかということです。Union Find アルゴリズムを使用して特定することは間違いなく可能ですが、この記事では DFS アルゴリズムに焦点を当てているため、Union Find アルゴリズムについては詳しく説明しません。 どのような状況でグリッド 2 の島 B がグリッド 1 の島 A のサブ島になることができますか? 島 B のすべての土地が島 A の土地でもある場合、島 B は島 A の子島になります。 逆に、島 B に陸地があり、島 A の対応する位置が海水である場合、島 B は島 A の子島ではありません。 次に、grid2 内のすべての島をトラバースし、サブ島になることができない島を除外し、残りの島をサブ島にします。 この考え方に基づいて、次のコードを直接記述できます。
この質問の背後にある考え方は、「閉じた島」の数を計算する考え方と多少似ていますが、後者は端に近い島を除外し、前者はサブ島になることができない島を除外する点が異なります。 島の数が異なるこれはこの記事の最後の島の質問です。最後なので、もちろん最も興味深いものです。 問題 694 は「異なる島の数」です。問題は、0 が海水、1 が陸地を表す 2 次元行列を入力することです。今回は、異なる島の数を計算することが求められます。関数のシグネチャは次のとおりです。
たとえば、質問では次の 2 次元行列を入力します。 島は 4 つありますが、左下隅と右上隅の島は同じ形をしているため、合計で 3 つの異なる島があり、アルゴリズムは 3 を返します。 明らかに、2 次元行列内の「島」を文字列などの型に変換する方法を見つけ、次に HashSet などのデータ構造を使用して重複を削除し、最後に異なる島の数を取得する必要があります。 アイランドを文字列に変換する場合、簡単に言えばシリアル化であり、シリアル化は簡単に言えばトラバーサルです。バイナリツリーのシリアル化とデシリアル化に関する前回の記事では、バイナリツリーと文字列間の変換について説明しましたが、ここでも同様です。 まず、同じ形状の島の場合、同じ開始点から開始すると、dfs 関数が移動する順序は同じでなければなりません。 トラバーサル順序は再帰関数内でハードコードされており、動的に変更されないためです。
したがって、トラバーサル順序は、下の図の 2 つの島のように、ある意味で島の形状を記述するために使用できます。 それらの走査順序が次のとおりであると仮定します。 下、右、上、元に戻す上、元に戻す右、元に戻す下 1、2、3、4 で上、下、左、右を表し、-1、-2、-3、-4 で上、下、左、右の元に戻すを表す場合、それらの移動順序は次のように表すことができます。 2、4、1、-1、-4、-2 これは、島のシリアル化の結果に相当します。 dfs を使用して島をトラバースするたびに、この数字の文字列が生成され、比較される限り、異なる島の数を計算できます。 この番号を生成するには、dfs 関数を少し変更し、トラバーサル順序を記録するための関数パラメータをいくつか追加する必要があります。
dir は方向を記録します。dfs 関数が再帰的に終了した後、sb はトラバーサル順序全体を記録します。実際、これは前のバックトラッキング アルゴリズム コア ルーチンで説明したバックトラッキング アルゴリズム フレームワークです。これらのアルゴリズムはすべて同じであることがわかります。 この dfs 関数を使用すると、簡単に処理できます。最終的なソリューション コードを直接記述できます。
このようにすれば問題は解決します。最初に dfs 関数を呼び出すときの dir パラメータが任意に記述できるのはなぜか、これは DFS とバックトラック アルゴリズムの微妙な違いに関係しています。グラフ アルゴリズムの基本は前回の記事で書いたので、ここでは詳しく説明しません。 上記は島シリーズ全体の問題の解答です。おそらくほとんどの人は前の問題を解くことができるでしょうが、最後の 2 つの問題はまだ比較的巧妙です。この記事が皆さんのお役に立てば幸いです。 |
<<: インタビュアー: 貪欲アルゴリズムとバックトラッキングアルゴリズムについて、どのように理解していますか?応用シナリオ?
>>: AIのおかげで売上が24%増加しました。このようなAI人材はどこで見つけられるのでしょうか?
「機械学習」、「人工知能」、「ディープラーニング」という 3 つの用語は混同されることが多いですが、...
機械学習とディープラーニングの違いは何だろうとよく疑問に思う方は、この記事を読んで、その違いを一般の...
[[433685]]ペアワイズアルゴリズムとは何ですか?次のテストシナリオの場合:ブラウザ: M、O...
自律型ドローン技術は、業界全体に変革をもたらす力として登場し、比類のない効率性と革新性を約束していま...
地球科学は、岩石、鉱物、土地の特性を研究するだけでなく、地球の気候、海洋、大気、生態系などの現象と原...
この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...
グーグルは8月14日、飛行機による気候への影響を大幅に軽減できる人工知能の分野で大きな進歩を遂げたと...
[[412418]] Google Cloud のお客様は、分散型サービス拒否 (DDoS) 保護...