そしてBFS
同様に、深さ優先探索(DFS)
もう一つの重要なアルゴリズム/探索木トラバーサル/図のため。あなたはまた、より抽象的なシーンを使用することができます。
述べたように、ツリーを横断、我々は使用することができるDFS
ため、注文トラバーサル、順トラバーサルにし、後順のトラバース。すべての3つのトラバーサル順に共通の分母があります:私たちは最も深いノードに到達ない限り、そうでない場合は、我々は戻って行くことはありません。
それはまたあるDFS
とBFS
の最も大きな違い、BFS
それは現在のノードのすべてのレベルへのアクセスを持っている場合を除き、深さで検討されることはありません。
原紙
再帰テンプレート
2つの実装がありますDFS
方法は。第一の方法は、再帰的です:
boolean DFS(Node cur, Node target, Set<Node> visited) {
return true if cur is target;
for (next : each neighbor of cur) {
if (next is not in visited) {
add next to visted;
return true if DFS(next, target, visited) == true;
}
}
return false;
}
我々は再帰的に実現した場合DFS
の時間を、どのスタックを使用していないようです。しかし、実際には、我々はまた、コールスタック(コールスタック)として知られている、システムが提供する暗黙のスタックを使用しています。
明示的なスタックテンプレート
利点再帰的な解決策は、実装が簡単であるということです。しかし、一つの大きな欠点がある:再帰の深さが高すぎる場合は、スタックオーバーフローを被るだろう。このケースでは、使用する場合がありますBFS
、または使用明示的なスタックを達成するためにDFS
。
boolean DFS(int root, int target) {
Set<Node> visited;
Stack<Node> s;
add root to s;
while (s is not empty) {
Node cur = the top element in s;
return true if cur is target;
for (Node next : the neighbors of cur) {
if (next is not in visited) {
add next to s;
add next to visited;
}
}
remove cur from s;
}
return false;
}
例
島の1.数
- 難易度:
Medium
タイトル説明
なる所定の'1'
(ランド)、及び'0'
二次元のグリッドコンピューティングの島の数からなる(水)。島は水に囲まれ、水平または垂直方向に隣接するランドに接続されているを通してです。あなたは、グリッドの四方を囲む水があると仮定することができます。
例1:
入力:
11110
11010
11000
00000
出力:1
例2:
入力:
11000
11000
00100
00011
出力:3
問題解決のためのアイデアと実現
私がしていたこの記事で使用する方法を示しBFS
、この質問を解決する問題は、使用しているという事実DFS
前者はまた、キュー維持する必要があるため、単純に幅優先探索の探索中に階層情報を。
使用DFS
問題解決次のように:
public class B200NumIslands {
public int numIslands(char[][] grid) {
int nr = grid.length;
if (nr == 0) return 0;
int nc = grid[0].length;
if (nc == 0) return 0;
int result = 0;
for (int r = 0; r < nr; r++) {
for (int c = 0; c < nc; c++) {
if (grid[r][c] == '1') {
result++;
dfs(grid, r, c);
}
}
}
return result;
}
private void dfs(char[][] grid, int r, int c) {
int nr = grid.length;
int nc = grid[0].length;
// 排除边界外的情况
if (r >= nr || c >= nc || r < 0 || c < 0) return;
// 排除边界外指定位置为 '0' 的情况
if (grid[r][c] == '0') return;
// 该位置为一个岛,标记为已探索
grid[r][c] = '0';
dfs(grid, r - 1, c); // top
dfs(grid, r + 1, c); // bottom
dfs(grid, r, c - 1); // left
dfs(grid, r, c + 1); // right
}
}
図2クローニング
- 難易度:
Medium
タイトル説明
あなたは無向通信あなたがこの図に戻って、参照にノード図を深いコピー(クローン)。
グラフの各ノードは、それは価値が含まれval(int)
、そのネイバーのリストを(list[Node]
)。
class Node {
public int val;
public List<Node> neighbors;
}
被写体を参照してより詳細な説明本明細書:
https://leetcode-cn.com/problems/clone-graph/
問題解決のためのアイデアと実現
理解することはより困難なタイトル、と指摘します。
- ためディープコピー、すべてのノードは、必要がある
new
すなわち、グラフ内の各ノードを通過する必要が、それは、溶液の使用を出て、インスタンス化DFS
またはBFS
でき、 - コピーした各ノードは、無限ループがスタックオーバーフローが発生しないようにマークされています。
ではDFS
、次のようにコードです:
class Solution {
public Node cloneGraph(Node node) {
HashMap<Node,Node> map = new HashMap<>();
return dfs(node, map);
}
private Node dfs(Node root, HashMap<Node,Node> map) {
if (root == null) return null;
if (map.containsKey(root)) return map.get(root);
Node clone = new Node(root.val, new ArrayList());
map.put(root, clone);
for (Node nei: root.neighbors) {
clone.neighbors.add(dfs(nei, map));
}
return clone;
}
}
3.目的と
- 難易度:
Medium
タイトル説明
負でない整数の配列、A1、A2、...、与えられた 、 との目標の数、S. -今、あなたは二つのシンボル+としています。任意の整数配列の場合、あなたはからできる+
または-
記号が以前に追加を選択します。
そして、シンボルの数を追加するためのすべての方法を返すことができ、最終的な配列はS.の目標数であります
例1:
输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释:
>-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
一共有5种方法让最终目标和为3。
注意:
1.非空の配列、およびno 20以上の長さ。
2.最初の配列ではなく、1,000以上。
3.最終結果は32ビット整数を保存できるように戻されます。
問題解決のためのアイデアと実現
私は使用にこの質問期待していなかった正直に言うとDFS
決意、または少なすぎる経験に暴力をタイトルが20を超えていない配列の長さは、20桁のシーケンスが言うように、この質問の暴力的な解決策は、完全に可能であり、時間をしません、チェンSiはまた、組み合わせ2^20
の組み合わせを:
public class Solution {
int count = 0;
public int findTargetSumWays(int[] nums, int S) {
dfs(nums, 0, 0, S);
return count;
}
private void dfs(int[] nums, int index, int sum, int S) {
if (index == nums.length) {
if (sum == S) count++;
} else {
dfs(nums, index + 1, sum + nums[index], S);
dfs(nums, index + 1, sum - nums[index], S);
}
}
}
4.バイナリツリーの前順
- 難易度:
Medium
タイトル説明
それを返すために前順でバイナリツリーを考えます。
高度:再帰的アルゴリズムは非常に簡単です、あなたは、反復アルゴリズムによってそれを行うことができますか?
問題解決のためのアイデアと実現
バイナリツリーは実際にポイントの非常に興味深い相関アルゴリズムの知識(この質問は非常に一般的ですので、私はインタビュー2333年に最も高い確率検定を考える...)ですが、私はこの知識のためのより詳細な問い合わせをたどる、この記事の一覧どちらのソリューション。
1.再帰
public class Solution {
// 1.递归法
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
dfs(root, list);
return list;
}
private void dfs(TreeNode node, List<Integer> list) {
if (node == null) return;
// 中序遍历:左中右
if (node.left != null)
dfs(node.left, list);
list.add(node.val);
if (node.right != null)
dfs(node.right, list);
}
}
2.スタック
public class Solution {
// 2.使用栈
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (!stack.isEmpty() || curr != null) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
list.add(curr.val);
curr = curr.right;
}
return list;
}
}
リファレンス&感謝
記事からの抜粋のほとんどはLeetCode
、スタックと深さ優先探索概要:
- https://leetcode-cn.com/explore/learn/card/queue-stack/219/stack-and-dfs/
例:
- https://leetcode-cn.com/problems/number-of-islands
- https://leetcode-cn.com/problems/clone-graph/
- https://leetcode-cn.com/problems/target-sum/
- https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
私について
こんにちは、私は清メイスニフを混乱あなたはあなたに貴重な記事、歓迎は❤️、また私に注意を歓迎思えば、ブログやGitHubの。
あなたは記事が何かので、さらに悪くなると考えられる場合は、またしてくださいに焦点を当て、より良い記事を書くために私を促す-ある日、私はそれの進捗状況か?