不确定此递归如何工作

时间:2018-08-24 03:21:07

标签: python recursion binary-tree

class Solution: 
    def findDuplicateSubtrees(self, root):
        self.res = []
        self.dic = {}
        self.dfs(root)
        return self.res

    def dfs(self, root):
        if not root: return '#'
        tree = self.dfs(root.left) + self.dfs(root.right) + str(root.val)

        if tree in self.dic and self.dic[tree] == 1:
            self.res.append(root)
        self.dic[tree] = self.dic.get(tree, 0) + 1

        return tree

这是一种在给定二叉树的情况下获取所有重复子树的解决方案。 我不确定tree = self.dfs(root.left) + self.dfs(root.right) + str(root.val)想要提供什么。

我知道它正在尝试进行后遍历,但是这部分实际上是如何工作的?

如果任何人都可以遵循此代码,那就太好了。谢谢。

2 个答案:

答案 0 :(得分:1)

最好从下往上解开递归。

  • 非节点(叶节点的子节点)将返回"#"
  • 具有值1的叶子将返回"##1"(因为它有两个非节点子节点)。
  • 具有两个叶子节点31的节点2将返回##1##23"##1"是左子节点的dfs"##2"是右子节点的dfs,而"3"是字符串化的当前节点的值。

这样,假设不存在任何值为23的节点,而另一个节点的值为空字符串,则可以看到,如果两个不同的节点产生##1##23,则它们是重复的子树。如果使用一些附加的分隔符(例如,该行末尾的分号将产生"##1;##2;3;)会更健壮,这足以使其更具可读性和更少歧义。如果使用列表,则更安全(但更慢)。

答案 1 :(得分:1)

基本上,变量tree可以看作是每个子树的编码字符串。并且我们使用全局字典self.dic来记住那些编码的字符串。

一个例子:

     A
  B      C
D   D  E   B
          D  D

按照级别顺序,二叉树可以描述为[[A], [B, C], [D, D, E, B], [#, #, #, #, #, #, D, D]],因此我们至少有两个重复的子树为[[B], [D, D]][D] 遵循代码,我们有

dfs(A)
  dfs(B)
    dfs(D) *save ##D, return ##D
    dfs(D) *find ##D, get one subtree, return ##D
  *save ##D##DB, return ##D##DB
  dfs(C)
  ...