スタックと深さ優先探索(DFS)


そしてBFS同様に、深さ優先探索(DFS)もう一つの重要なアルゴリズム/探索木トラバーサル/図のため。あなたはまた、より抽象的なシーンを使用することができます。

述べたように、ツリーを横断、我々は使用することができるDFSため、注文トラバーサル順トラバーサルにし、後順のトラバースすべての3つのトラバーサル順に共通の分母があります:私たちは最も深いノードに到達ない限り、そうでない場合は、我々は戻って行くことはありません

それはまたあるDFSBFSの最も大きな違い、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/

問題解決のためのアイデアと実現

理解することはより困難なタイトル、と指摘します。

  1. ためディープコピー、すべてのノードは、必要があるnewすなわち、グラフ内の各ノードを通過する必要が、それは、溶液の使用を出て、インスタンス化DFSまたはBFSでき、
  2. コピーした各ノードは、無限ループがスタックオーバーフローが発生しないようにマークされています。

では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の

あなたは記事が何かので、さらに悪くなると考えられる場合は、またしてくださいに焦点を当て、より良い記事を書くために私を促す-ある日、私はそれの進捗状況か?

公開された99元の記事 ウォンの賞賛396 ビュー470 000 +

おすすめ

転載: blog.csdn.net/mq2553299/article/details/104304567