LeetCode 988:回溯和深度优先搜索(DFS)的区别

Posted

技术标签:

【中文标题】LeetCode 988:回溯和深度优先搜索(DFS)的区别【英文标题】:LeetCode 988: Difference between backtracking and depth first search (DFS) 【发布时间】:2020-06-12 03:07:55 【问题描述】:

我对@9​​87654321@(从叶子开始的最小字符串)中的回溯解决方案和 DFS 解决方案感到困惑。

如果使用StringBuilder实现,则需要这行代码:sb.deleteCharAt(sb.length() - 1),而使用String实现时,不需要该行。

谁能帮助解决我的困惑?

回溯(使用 StringBuilder)

String ans = "";

public String smallestFromLeaf(TreeNode root) 
    helper(root, new StringBuilder());
    return ans;
 

private void helper(TreeNode root, StringBuilder sb) 
    if (root == null) return;
    sb.append((char)('a' + root.val));
    if (root.left == null && root.right == null) 
    String candidate = sb.reverse().toString();
    if (ans == "" || candidate.compareTo(ans) < 0) 
        ans = candidate;
        sb.reverse();
    

    helper(root.left, sb);
    helper(root.right, sb);
    sb.deleteCharAt(sb.length() - 1);

DFS(使用字符串)

String ans = "";

public String smallestFromLeaf(TreeNode root) 
    helper(root, "");
    return ans;


private void helper(TreeNode root, String s) 
    if (root == null) return;

    s = (char)('a' + root.val) + s;
    if (root.left == null && root.right == null) 
        String candidate = s;
        if (ans == "" || candidate.compareTo(ans) < 0) 
            ans = candidate;
        
        return;
    

    helper(root.left, s);
    helper(root.right, s);

【问题讨论】:

【参考方案1】:

字符串在 Java 中是不可变的,所以这意味着这一行,

s = (char)('a' + root.val) + s;

将创建递归函数接收的新字符串对象。因此,回溯解决方案通常没有“撤消”步骤。而在回溯解决方案中,只创建并传递了一个 StringBuilder 对象。当我们从回溯解决方案中的基本情况返回(即到达叶节点)时,我们必须撤消将字符添加到字符串构建器的步骤。

我建议你在回溯解决方案的sb的状态以及DFS中的s的值中添加打印语句,看看它如何改变递归的每一步。

【讨论】:

以上是关于LeetCode 988:回溯和深度优先搜索(DFS)的区别的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode之深度优先搜索&回溯专题-980. 不同路径 III(Unique Paths III)

回溯法与深度优先搜索

988. 从叶结点开始的最小字符串

988. 从叶结点开始的最小字符串

广度优先和深度优先算法

leetcode 79. Word Search 单词搜索