リートコードにおける配列のネスティングとは?最適解のための2025年DFSガイド
配列の入れ子は、最初は複雑に見えるかもしれませんが、正しい戦略によって、魅力的な挑戦に変わります。このガイドでは、LeetCodeの問題565「配列の入れ子」を徹底的に調べ、深さ優先探索(DFS)を使った解き方の包括的な探求を提供します。問題の説明、DFSが効果的な方法である理由の説明、アルゴリズムの分解、詳細なコードサンプルの提供、最適化の戦術について説明します。最後には、配列の入れ子とDFSの両方をしっかりと理解し、同様の問題に自信を持って対処できるようになります。
キーポイント
LeetCodeの配列ネスティングの問題文(問題565)を理解する。
深さ優先探索(DFS)が配列内のサイクルを特定するのに適している理由を学ぶ
DFSアルゴリズムを明確で管理しやすいステップに分解します。
JavaとPythonのコード実装をレビューします。
時間と空間の複雑さに関する考慮事項を分析します。
訪問配列の採用などの最適化手法を発見する。
ステップ・バイ・ステップの例に従って理解を深める。
配列の入れ子を理解する
問題文リートコード565
問題の正式な定義から始めましょう。n' 個の整数を含む配列 'nums' が与えられ、それぞれの値 'nums[i]' は [0, n - 1] の範囲にある。この配列は0からn-1までの数の並べ替えを表している.あなたの目的は、この配列に従って形成される最長の集合(またはサイクル)の長さを決定することである:
- 任意のインデックス'i'から始める.
- 集合の後続の要素は'nums[i]'である.
- その次の要素は「nums[nums[i]]」で、このパターンを続ける。
- この処理は、現在の集合内ですでに遭遇した要素に到達するまで続けられる。
ゴールは、配列内で見つかったそのような集合の最大の長さを返すことである。この問題では、配列構造をナビゲートし、周期的なパターンを識別する能力が試される。
深さ優先探索(DFS)が適している理由
深さ優先探索(DFS)は、サイクルの検出を含む問題に対して直感的で効果的な戦略です。配列を有向グラフとして概念化することができ、各インデックスは別のインデックスを指示します。DFSは、バックトラックする前に各分岐に沿って可能な限りトラバースすることで、そのようなグラフを系統的に探索することに長けている。DFSが配列の入れ子に適している主な理由は以下の通りである:
- 系統的な探索:DFSは、次の経路に移る前に、可能性のある各経路を徹底的に探索し、あらゆるサイクルの完全な探索を保証します。
- サイクルの検出:探索中に、現在のパスですでに訪問したノードに遭遇した場合、サイクルの特定に成功したことになります。このためには、訪問ノードの追跡が不可欠です。
- 効率:ノードを訪問済みとマークすることで、冗長な計算を防ぎ、解全体を最適化します。
代替ソリューション
代替案1:DFSの反復的実装
この深さ優先探索の反復的アプローチは、再帰の代替手段を提供します。以下のJavaコードは、再帰を行わずにサイクルを検出し、その長さを計算することで、潜在的なスタック・オーバーフローの問題を回避している:
import java.util.Arrays;class Solution {public int arrayNesting(int[] nums) {int n = nums.length;boolean[] visited = new boolean[n];int maxLength = 0;for (int start = 0; start) この実装の主な利点は
- 次の
とおりです:
- 反復ループが再帰に取って代わるため、スタック深度に関する懸念がなくなる
- :どの要素が処理されたかを効率的に追跡するために、別の配列を引き続き使用する
- :
メモリ効率:- 反復処理により、再帰呼び出しスタックに関連するメモリ・オーバーヘッドが削減される。
代替案2:インプレース・サイクル長計算この
方法は、入力配列内でサイクル長を直接計算することで、よりメモリ効率の高いソリューションを提供する。以下のPythonコードは、このインプレースアプローチを示しています:
class Solution:def arrayNesting(self, nums: List[int]) -> int:n = len(nums)max_length = 0for i in range(n):if nums[i] != -1:# このインデックスが処理されていない場合のみ処理を進める start = icount = 0while nums[start] != -1:next_index = nums[start]nums[start] = -1# -1に設定することで訪問済みとみなすstart = next_indexcount += 1max_length = max(max_length, count)return max_length# 例題usagenums = [5,4,0,3,1,6,2]solution = Solution()result = solution.arrayNesting(nums)print(f "Length of the longest cycle: {result}") # 出力:4
この手法の
主な
利点は以下の通り:
- メモリフットプリントの削減:
メモリフットプリントの- 削減:元のリストを修正することで、別の訪問済み配列の必要性を排除
- します
- :
- 最適化されたパフォーマンス:
DFSアルゴリズム:ステップ・バイ・ステップの実装visited
配列
nums配列と同じ長さのvisitedという名前のブール配列を使用する。visited[i]は、インデックス'i'の要素を探索した時点で真に設定される。
DFS関数 (dfs(nums, i, visited))
この再帰関数は、 'nums' 配列、開始インデックス 'i' および 'visited' 配列を受け取る。インデックス 'i' から始まる深さ優先探索を行い、発見されたサイクルの長さを返す。
基本ケース: visited[i]が既に真であれば、この要素は既に計測したサイクルの一部であることを示す。この関数は冗長な作業を避けるために0を返す。

Visitedとしてマーク:異なる開始点から同じサイクルに再び入ることを防ぐために、直ちにvisited[i]をtrueとしてマーク
します
:
next = nums[i]を使用して次のインデックスを決定し、dfs(nums, next, visited)を再帰的に呼び出してサイクルの探索を続行
する
:
サイクルの合計の長さは、1(現在のノードの長さ)に再帰呼び出しから返された長さを加えたものになります。この値が返されます。cycle_length = 1 + dfs(nums, next, visited).
メイン関数 (arrayNesting(nums))
- 'visited' 配列を初期化します:サイズnの真偽値配列を作成し、すべての値をfalseに設定する。
- maxLength'を0に初期化する:この変数は、見つかった最長のサイクルを追跡する
- :nums' 配列の各インデックス 'i' をループする
- :
visited[i]がfalseの場合、そのインデックスからDFS探索を開始する - :
max_length = Math.max(max_length, dfs(nums, i, visited)). - Return 'maxLength':
pricetingtitlepricingDFSアプローチの長所と短所
長所
効果的なサイクルの検出:この配列のようなグラフ構造のサイクルを見つけるのに適している
:
明確な再帰構造:再帰的な性質は、問題を解くためのわかりやすく論理的な流れを提供します。
短所
スタック・オーバーフローの
可能性
:入力サイズが非常に大きい場合、深い再帰はスタックオーバーフローエラーを引き起こす可能性が
ある
:
配列の入れ子にDFSを使用する中核的な機能と利点主要な
コード概念とその利点
配列の入れ子問題を解くためのDFS実装には、成功に貢献するいくつかの重要なプログラミング概念が組み込まれています:
- 再帰性:DFSの再帰的な性質により、配列の各潜在経路を完全に探索することができ、サイクルを見逃すことがない
- :この配列は、アルゴリズムがどの要素も2回以上処理しないようにする、効率のための基本で
- ある
- :
- アルゴリズムが本質的にサイクルを検出するのは、すでに現在のトラバーサル・パスの一部になっているノードを訪問しようとするとき
- です
- :
- 各サイクルの長さは、DFSが配列内を進行する際にその場で計算さ
- れます
- :
- 最大
化ステップ:- 最大長を継続的に更新することで、最終的な答えが見つかった最大のサイクルであることを保証
- します
- 。
コード例による理解の向上
DFSプロセスを説明する
ために
、次の例を考えてみましょう。
配列nums = [5,4,0,3,1,6,2]が与えられた場合、DFSアルゴリズムは次のように実行されます。
- インデックス5から、インデックス5を訪問済みとマークし、
nums[5]に移動し、nums[5]は6である。 - インデックス6から、インデックス6を訪問済みとマークし、
nums[6]に移動し、nums[6]は2である。 - インデックス2において、アルゴリズムはそれを訪問済みとマークし、
nums[2]が0であることを発見
する
- 。0は既に訪問済みであるので、サイクル[0, 5, 6, 2]は長さ4の完全なものである
。
この深い探索により、経路が以前に訪れたノードにループして戻り、サイクルを形成していることを自然に検出することができる。幅優先探索(BFS)は最短経路を見つけるのに適しており、この特定のタスクには直感的でない。
この問題は余分なスペースを使わずに解決できますか?
はい、元の入力配列を変更することでO(1)スペースで解決できます。別の'visited'配列の代わりに、'nums'配列内の訪問済みインデックスを直接マークし、その値を-1のようなセンチネル値に変更することができます。 このアプローチは元の入力データを変更することに注意することが重要です。
配列内の数値の範囲(0からn-1)は解にどのような影響を与えるか?
すべての値が0からn-1の間であるという制約は非常に重要である。これは、配列内のすべての値が配列自体の中で有効なインデックスであることを保証します。
関連する質問
nums[i]が[0, n - 1]の範囲にあるn個の整数の配列numsが与えられたとき、配列内の最長のサイクルを見つけて返す関数を書くことができますか?JavaとPythonの両方の実装を用意し
なさい
。
以下は、JavaとPythonの実装で、最も長いサイクルの長さを見つけるように設計されています:import java.util.Arrays;class Solution {public int arrayNesting(int[] nums) {int n = nums.length;boolean[] visited = new boolean[n];int maxLength = 0;for (int i = 0; i int:n = len(nums)visited = [False] * nmax_length = 0for i in range(n):if not visited[i]:max_length = max(max_length, self.dfs(nums, i, visited))return max_lengthdef dfs(self, nums: List[int], start: int, visited: List[bool]) -> int:if visited[start]:return 0visited[start] = Truenext_val = nums[start]cycle_length = 1 + self.dfs(nums, next_val, visited)return cycle_length# 例 Usagenums = [5,4,0,3,1,6,2]solution = Solution()result = solution.arrayNesting(nums)print(f "Length of the longest cycle: {result}")# 出力:4これらの実装は、不要な再処理を防ぐために訪問された配列を使用して、サイクルを効率的に検出し、その長さを計算するように最適化されている。
関連記事
AIトークンは新たなサインボーナスなのか、それとも単なる事業経費に過ぎないのか?
今週、シリコンバレーで以前から話題になっていたあるテーマが、ついに広く注目を集めることになった。それは、報酬の一部としてAIトークンを支給するというものだ。その仕組みは単純で、企業がエンジニアに対して給与、株式、ボーナスだけでなく、Claude、ChatGPT、Geminiといったツールを動かす計算単位であるAIトークンのプールも提供するというものだ。 エンジニアはこれらのトークンを使用して、エー
Metaによる天然ガス需要の急増が、サウスダコタ州の電力網を支えることになるかもしれない
データセンターは巨大化し、その電力消費量は今や米国の州全体に匹敵するほどになっています。MetaのHyperion AIデータセンターを例に挙げると、完成すればサウスダコタ州と同じだけの電力を消費することになります。Metaは最近、270億ドル規模のデータセンターを支えるため、すでに計画されている3基に加え、さらに7基の天然ガス発電所への資金提供を発表した。ルイジアナ州に建設されるこれら10基の発
裁判所の提出書類によると、トランプ氏が関係終了を宣言してから1週間ほど後に、国防総省はアンソロピックに対し、アラインメントが間近であることを伝えていた
アンソロピック社は金曜日午後遅く、カリフォルニア州の連邦裁判所に2通の宣誓供述書を提出し、同社が「国家安全保障にとって容認できないリスク」であるとする国防総省の主張に異議を唱えた。同社は、政府の主張が技術的な誤解に基づいているほか、紛争に至るまでの数ヶ月にわたる交渉の過程で一度も取り上げられなかった主張に依拠していると主張している。これらの宣誓供述書は、3月24日(火)にサンフランシスコのリタ・リ
関連特集おすすめ
コメント (1)
0/500
配列の入れ子は、最初は複雑に見えるかもしれませんが、正しい戦略によって、魅力的な挑戦に変わります。このガイドでは、LeetCodeの問題565「配列の入れ子」を徹底的に調べ、深さ優先探索(DFS)を使った解き方の包括的な探求を提供します。問題の説明、DFSが効果的な方法である理由の説明、アルゴリズムの分解、詳細なコードサンプルの提供、最適化の戦術について説明します。最後には、配列の入れ子とDFSの両方をしっかりと理解し、同様の問題に自信を持って対処できるようになります。
キーポイント
LeetCodeの配列ネスティングの問題文(問題565)を理解する。
深さ優先探索(DFS)が配列内のサイクルを特定するのに適している理由を学ぶ
DFSアルゴリズムを明確で管理しやすいステップに分解します。
JavaとPythonのコード実装をレビューします。
時間と空間の複雑さに関する考慮事項を分析します。
訪問配列の採用などの最適化手法を発見する。
ステップ・バイ・ステップの例に従って理解を深める。
配列の入れ子を理解する
問題文リートコード565
問題の正式な定義から始めましょう。n' 個の整数を含む配列 'nums' が与えられ、それぞれの値 'nums[i]' は [0, n - 1] の範囲にある。この配列は0からn-1までの数の並べ替えを表している.あなたの目的は、この配列に従って形成される最長の集合(またはサイクル)の長さを決定することである:
- 任意のインデックス'i'から始める.
- 集合の後続の要素は'nums[i]'である.
- その次の要素は「nums[nums[i]]」で、このパターンを続ける。
- この処理は、現在の集合内ですでに遭遇した要素に到達するまで続けられる。
ゴールは、配列内で見つかったそのような集合の最大の長さを返すことである。この問題では、配列構造をナビゲートし、周期的なパターンを識別する能力が試される。
深さ優先探索(DFS)が適している理由
深さ優先探索(DFS)は、サイクルの検出を含む問題に対して直感的で効果的な戦略です。配列を有向グラフとして概念化することができ、各インデックスは別のインデックスを指示します。DFSは、バックトラックする前に各分岐に沿って可能な限りトラバースすることで、そのようなグラフを系統的に探索することに長けている。DFSが配列の入れ子に適している主な理由は以下の通りである:
- 系統的な探索:DFSは、次の経路に移る前に、可能性のある各経路を徹底的に探索し、あらゆるサイクルの完全な探索を保証します。
- サイクルの検出:探索中に、現在のパスですでに訪問したノードに遭遇した場合、サイクルの特定に成功したことになります。このためには、訪問ノードの追跡が不可欠です。
- 効率:ノードを訪問済みとマークすることで、冗長な計算を防ぎ、解全体を最適化します。
代替ソリューション
代替案1:DFSの反復的実装
この深さ優先探索の反復的アプローチは、再帰の代替手段を提供します。以下のJavaコードは、再帰を行わずにサイクルを検出し、その長さを計算することで、潜在的なスタック・オーバーフローの問題を回避している:
) この実装の主な利点は とおりです: 方法は、入力配列内でサイクル長を直接計算することで、よりメモリ効率の高いソリューションを提供する。以下のPythonコードは、このインプレースアプローチを示しています: この手法の 利点は以下の通り: nums配列と同じ長さのvisitedという名前のブール配列を使用する。 この再帰関数は、 'nums' 配列、開始インデックス 'i' および 'visited' 配列を受け取る。インデックス 'i' から始まる深さ優先探索を行い、発見されたサイクルの長さを返す。 基本ケース: import java.util.Arrays;class Solution {public int arrayNesting(int[] nums) {int n = nums.length;boolean[] visited = new boolean[n];int maxLength = 0;for (int start = 0; start
メモリ効率:代替案2:インプレース・サイクル長計算この
class Solution:def arrayNesting(self, nums: List[int]) -> int:n = len(nums)max_length = 0for i in range(n):if nums[i] != -1:# このインデックスが処理されていない場合のみ処理を進める start = icount = 0while nums[start] != -1:next_index = nums[start]nums[start] = -1# -1に設定することで訪問済みとみなすstart = next_indexcount += 1max_length = max(max_length, count)return max_length# 例題usagenums = [5,4,0,3,1,6,2]solution = Solution()result = solution.arrayNesting(nums)print(f "Length of the longest cycle: {result}") # 出力:4主なDFSアルゴリズム:ステップ・バイ・ステップの実装visited
配列
visited[i]は、インデックス'i'の要素を探索した時点で真に設定される。DFS関数 (dfs(nums, i, visited))
visited[i]が既に真であれば、この要素は既に計測したサイクルの一部であることを示す。この関数は冗長な作業を避けるために0を返す。
Visitedとしてマーク:異なる開始点から同じサイクルに再び入ることを防ぐために、直ちにvisited[i]をtrueとしてマーク
します
:
next = nums[i]を使用して次のインデックスを決定し、dfs(nums, next, visited)を再帰的に呼び出してサイクルの探索を続行
する
:
サイクルの合計の長さは、1(現在のノードの長さ)に再帰呼び出しから返された長さを加えたものになります。この値が返されます。cycle_length = 1 + dfs(nums, next, visited).
メイン関数 (arrayNesting(nums))
- 'visited' 配列を初期化します:サイズnの真偽値配列を作成し、すべての値をfalseに設定する。
- maxLength'を0に初期化する:この変数は、見つかった最長のサイクルを追跡する
- :nums' 配列の各インデックス 'i' をループする
- :
visited[i]がfalseの場合、そのインデックスからDFS探索を開始する - :
max_length = Math.max(max_length, dfs(nums, i, visited)). - Return 'maxLength':
pricetingtitlepricingDFSアプローチの長所と短所
長所
効果的なサイクルの検出:この配列のようなグラフ構造のサイクルを見つけるのに適している
:
明確な再帰構造:再帰的な性質は、問題を解くためのわかりやすく論理的な流れを提供します。
短所
スタック・オーバーフローの
可能性
:入力サイズが非常に大きい場合、深い再帰はスタックオーバーフローエラーを引き起こす可能性が
ある
:
配列の入れ子にDFSを使用する中核的な機能と利点主要な
コード概念とその利点
配列の入れ子問題を解くためのDFS実装には、成功に貢献するいくつかの重要なプログラミング概念が組み込まれています:
- 再帰性:DFSの再帰的な性質により、配列の各潜在経路を完全に探索することができ、サイクルを見逃すことがない
- :この配列は、アルゴリズムがどの要素も2回以上処理しないようにする、効率のための基本で
- ある
- :
- アルゴリズムが本質的にサイクルを検出するのは、すでに現在のトラバーサル・パスの一部になっているノードを訪問しようとするとき
- です
- :
- 各サイクルの長さは、DFSが配列内を進行する際にその場で計算さ
- れます
- :
- 最大
化ステップ:- 最大長を継続的に更新することで、最終的な答えが見つかった最大のサイクルであることを保証
- します
- 。
コード例による理解の向上
DFSプロセスを説明する
ために
、次の例を考えてみましょう。
配列nums = [5,4,0,3,1,6,2]が与えられた場合、DFSアルゴリズムは次のように実行されます。
- インデックス5から、インデックス5を訪問済みとマークし、
nums[5]に移動し、nums[5]は6である。 - インデックス6から、インデックス6を訪問済みとマークし、
nums[6]に移動し、nums[6]は2である。 - インデックス2において、アルゴリズムはそれを訪問済みとマークし、
nums[2]が0であることを発見
する
- 。0は既に訪問済みであるので、サイクル[0, 5, 6, 2]は長さ4の完全なものである
。
この深い探索により、経路が以前に訪れたノードにループして戻り、サイクルを形成していることを自然に検出することができる。幅優先探索(BFS)は最短経路を見つけるのに適しており、この特定のタスクには直感的でない。
この問題は余分なスペースを使わずに解決できますか?
はい、元の入力配列を変更することでO(1)スペースで解決できます。別の'visited'配列の代わりに、'nums'配列内の訪問済みインデックスを直接マークし、その値を-1のようなセンチネル値に変更することができます。 このアプローチは元の入力データを変更することに注意することが重要です。
配列内の数値の範囲(0からn-1)は解にどのような影響を与えるか?
すべての値が0からn-1の間であるという制約は非常に重要である。これは、配列内のすべての値が配列自体の中で有効なインデックスであることを保証します。
関連する質問
nums[i]が[0, n - 1]の範囲にあるn個の整数の配列numsが与えられたとき、配列内の最長のサイクルを見つけて返す関数を書くことができますか?JavaとPythonの両方の実装を用意し
なさい
。
以下は、JavaとPythonの実装で、最も長いサイクルの長さを見つけるように設計されています:import java.util.Arrays;class Solution {public int arrayNesting(int[] nums) {int n = nums.length;boolean[] visited = new boolean[n];int maxLength = 0;for (int i = 0; i int:n = len(nums)visited = [False] * nmax_length = 0for i in range(n):if not visited[i]:max_length = max(max_length, self.dfs(nums, i, visited))return max_lengthdef dfs(self, nums: List[int], start: int, visited: List[bool]) -> int:if visited[start]:return 0visited[start] = Truenext_val = nums[start]cycle_length = 1 + self.dfs(nums, next_val, visited)return cycle_length# 例 Usagenums = [5,4,0,3,1,6,2]solution = Solution()result = solution.arrayNesting(nums)print(f "Length of the longest cycle: {result}")# 出力:4これらの実装は、不要な再処理を防ぐために訪問された配列を使用して、サイクルを効率的に検出し、その長さを計算するように最適化されている。
AIトークンは新たなサインボーナスなのか、それとも単なる事業経費に過ぎないのか?
今週、シリコンバレーで以前から話題になっていたあるテーマが、ついに広く注目を集めることになった。それは、報酬の一部としてAIトークンを支給するというものだ。その仕組みは単純で、企業がエンジニアに対して給与、株式、ボーナスだけでなく、Claude、ChatGPT、Geminiといったツールを動かす計算単位であるAIトークンのプールも提供するというものだ。 エンジニアはこれらのトークンを使用して、エー
Metaによる天然ガス需要の急増が、サウスダコタ州の電力網を支えることになるかもしれない
データセンターは巨大化し、その電力消費量は今や米国の州全体に匹敵するほどになっています。MetaのHyperion AIデータセンターを例に挙げると、完成すればサウスダコタ州と同じだけの電力を消費することになります。Metaは最近、270億ドル規模のデータセンターを支えるため、すでに計画されている3基に加え、さらに7基の天然ガス発電所への資金提供を発表した。ルイジアナ州に建設されるこれら10基の発
裁判所の提出書類によると、トランプ氏が関係終了を宣言してから1週間ほど後に、国防総省はアンソロピックに対し、アラインメントが間近であることを伝えていた
アンソロピック社は金曜日午後遅く、カリフォルニア州の連邦裁判所に2通の宣誓供述書を提出し、同社が「国家安全保障にとって容認できないリスク」であるとする国防総省の主張に異議を唱えた。同社は、政府の主張が技術的な誤解に基づいているほか、紛争に至るまでの数ヶ月にわたる交渉の過程で一度も取り上げられなかった主張に依拠していると主張している。これらの宣誓供述書は、3月24日(火)にサンフランシスコのリタ・リ





家






