0

在过去的几天里,我一直在与树木和蟒蛇作斗争。大多数情况下,树中的递归给我带来了麻烦。我要解决的问题是在二叉树中找到第一个共同祖先。有很多解决方案声称已经做到了这一点,但它们都是针对二叉搜索树的,而不是二叉树。在二叉树的情况下,节点没有排序,所以左边小于右边。我知道我应该使用哪种方法,但我在递归部分失败了:(编辑:问题表明我不能使用额外的数据结构或存储)

class Node:

    """docstring for Node"""
    def __init__(self, data):
        self.data = data
        self.left=None
        self.right=None

def findNode(self,target):
    if self==None:
        return 0
    if self.data==target:
        return 1
    return self.findNode(self.left,target) or self.findNode(self.right,target)

def firstCommonAncestor(self,p,q):
    if self==None:
        return 0
    if self.left.data==p and self.right.data==q:
        return self.data
    if findNode(self.left,p) and findNode(self.right,q):
       return 1

root=Node(2)
root.left=Node(5)
root.right=Node(4)
root.left.left=Node(9)
root.left.right=Node(7)
print firstCommonAncestor(root,9,7)

我编辑了代码以使问题更清楚。findNode(self.left,p) 和 findNode(self.right,q) 应该返回 1,因为两个节点都存在。但是,当 findNode(self.right,q) 没有从根开始搜索时。我知道我应该实现递归调用,但我尝试过的一切都失败了。如果有人可以提供一些关于我做错了什么的指示,将不胜感激!(第一个CommonAncestor 还没有实现,所以这并不重要。它现在没有做太多)。编辑:这是破解编码面试的一个问题。

4

5 回答 5

1

(只是给你一个提示为什么它不工作)

当您搜索 y 时,它不会回到根目录。您的代码正在做正确的事情。您找不到 Node(7) 的原因是因为您的数据。

这是你的树。

         2
         |
      -------
     5       4
  -------
  9     7 

您的 x 搜索是 findNode(Node(5), 9) 找到 9。

虽然您的 y 搜索是 findNode(Node(4), 7) ,但它当然永远找不到 7

希望有帮助。

于 2013-11-14T23:54:44.263 回答
0

另一个提示:您的实例方法脱离了类,只是普通的全局方法(这不仅仅是缩进的问题,因为您也以错误的方式调用它们)。这是 的正确定义findNode

class Node:

    """docstring for Node"""
    def __init__(self, data):
        self.data = data
        self.left=None
        self.right=None

    def findNode(self,target):
        result = None

        if self.data == target:
            return self

        result = self.left.findNode(target) if self.left else None
        if not result:
            result = self.right.findNode(target) if self.right else None

        return result

    def firstCommonAncestor(self, p, q):
        pass #TODO

在该findNode方法中,您还有一个如何调用它的示例。您还应该在firstCommonAncestor方法中解决此问题。

于 2013-11-15T00:01:13.173 回答
0
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

    def isAncestor(self, p, q):
        ret = 0
        if self.data == None:
            return ret
        if (self.data == p):
            ret += 1
        if self.data == q:
            ret += 1
        if ret == 2:
            return ret
        if self.left!=None:
            ret += self.left.isAncestor(p, q)
        if ret == 2:
            return ret
        if self.right!=None:
            return ret + self.right.isAncestor(p ,q)
        return ret

    def commonAncestor(self, p, q):
        if q == p and (self.left.data == q or self.right.data == q):
            return self
        lNodes = self.left.isAncestor(p, q)
        if lNodes == 2:
            if self.left.data == p or self.left.data == q:
                return self.left
            else:
                return self.left.commonAncestor(p, q)
        elif lNodes == 1:
            if self.data == p:
                return p
            elif self.data == q:
                return q

        rNodes = self.right.isAncestor(p, q)
        if rNodes == 2:
            if self.right.data == p or self.right.data == q:
                return self.right
            else:
                return self.right.commonAncestor(p, q)
        elif rNodes == 1:
            if self.data == p:
                return p
            elif self.data == q:
                return q

        if lNodes == 1 and rNodes ==1:
            return self
        else:
            return None


"""
             2
           /   \
          5     4
        /  \   /  \
       9    7     11
                    \
                    12
"""
if __name__ == '__main__':
    root=Node(2)
    root.left=Node(2)
    root.right=Node(4)
    root.right.right=Node(11)
    root.left.left=Node(9)
    root.left.right=Node(7)
    root.right.right.right=Node(12)
    common = root.commonAncestor(2,2)
    if common != None:
        print common.data
    else:
        print "Not found"
于 2013-11-23T21:41:07.993 回答
-1

由于树没有排序,因此无论如何您都必须搜索很多。并且由于不允许您使用额外的数据结构,因此您有重复大量搜索的危险。

因此递归到叶节点一次,然后在返回组合数据时可能是最有效的。这是 O(n),但单次搜索也是如此。

所以这就是下面的代码试图做的。搜索方法返回(a's parent, b's parent),如果它们不同,但都设置了,那么我们在共同的祖先。

def search(self, a, b):
    ap1 = ap2 = ap3 = bp1 = bp2 = bp3 = None
    # parents to left
    if self.left:
        ap1, bp1 = self.left.search(a, b)
    # parents to right
    if self.right:
        ap2, bp2 = self.right.search(a, b)
    # are we an immediate "parent" ourselves?
    if self.data == a: 
        ap3 = self
    elif self.data == b:
        bp3 = self
    # only one of the above can succeed, so find it
    ap = ap1 or ap2 or ap3
    bp = bp1 or bp2 or bp3
    # if we are the point where two paths meet at the common
    # ancestor, return ourselves
    if ap and bp and ap != bp:
        return self, self
    # otherwise, return what we have
    else:
        return ap, bp
于 2013-11-15T00:02:15.123 回答
-1

编辑:重新设计的解决方案使其更清洁并解决评论中的问题

有一个非常有效的解决方案,但有点复杂。它涉及钻入树并跟踪您是否在返回时找到了第一个或第二个值。如果在某个时候您发现(第一个和第二个)都返回该节点,它将成为您的共同祖先。

这是更有效的解决方案,但如果您有重复项,则它不起作用,但它可以帮助您了解想法并解决重复情况:

class Node:
    """docstring for Node"""
    def __init__(self, data):
        self.data = data
        self.left=None
        self.right=None

    def union(self, u1, u2):
        res = u1[0] or u2[0], u1[1] or u2[1], u1[2] or u2[2]
        if res[0] and res[1] and not res[2]:
            return res[0], res[1], self
        return res

    def doCommon(self, p, q):
        # recursion base case
        l = (False, False, None)
        r = (False, False, None)
        if self.left:
            l = self.left.doCommon(p, q)
        if self.right:
            r = self.right.doCommon(p, q)

        res = self.union(l, r)
        if res[0] and res[1]:
            return res

        if self.data == p:
            return self.union((True, False, None), res)
        if self.data == q:
            return self.union((False, True, None), res)
        return res

    def common(self, p, q):
        return self.doCommon(p, q)[2]



if __name__ == '__main__':
    root=Node(2)
    root.left=Node(5)
    root.right=Node(4)
    root.left.left=Node(9)
    root.left.right=Node(7)
    res = root.common(9,7)
    if res != None:
        print res.data
    else:
        print "Not found"
于 2013-11-14T23:20:45.097 回答