Python程序员面试算法宝典---解题总结: 第三章 二叉树 3.8 如何找出排序二叉树上任意两个结点 的最近共同父节点

# -*- coding: utf-8 -*-

'''
Python程序员面试算法宝典---解题总结: 第三章 二叉树 3.8 如何找出排序二叉树上任意两个结点
的最近共同父节点

题目:
对于一棵给定的排序二叉树,求两个结点的共同父结点,例如在下图中,结点1和结点5的共同
父结点为3。
                                6
                3                               9
        2               5               8               10
    1               4               7

分析:
寻找公共父节点,一种简单的方法就是:
确定从根节点到第一个节点的路径path1(假设根节点为6,第一个节点为1,
则路径为: 6,3,2,1),确定从根节点到第二个节点的路径path2
(假设根节点为6,第二个节点为5,则路径为: 6,3,5)
则同事遍历path1和path2,最后一个相同的元素即为最近的公共父节点

关键:
1 书上解法
假设不是二叉排序树,而是普通的树,则需要使用递归来做,
用一个栈来存储路径

2 栈的实现
可以用数组实现

参考:
Python程序员面试算法宝典
'''


def findNearestCommonAncestor(root, findValue):
    path = list()
    if not root:
        return False, path
    if findValue is None:
        return False, path
    while root:
        if root.data == findValue:
            path.append(root.data)
            return True, path
        elif root.data < findValue:
            path.append(root.data)
            root = root.right
        else:
            path.append(root.data)
            root = root.left
    return False, path


class BinaryTreeNode(object):

    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


'''
                                6
                3                               9
        2               5               8               10
    1               4               7
'''
def buildTree(data, rootValue):
    # root = BinaryTreeNode(6)
    # node1 = BinaryTreeNode(3)
    # node2 = BinaryTreeNode(9)
    # node3 = BinaryTreeNode(2)
    # node4 = BinaryTreeNode(5)
    # node5 = BinaryTreeNode(8)
    # node6 = BinaryTreeNode(10)
    # node7 = BinaryTreeNode(1)
    # node8 = BinaryTreeNode(4)
    # node9 = BinaryTreeNode(7)
    nodeDict = dict()
    for value in data:
        node = BinaryTreeNode(value)
        nodeDict[value] = node
    nodeDict[6].left = nodeDict[3]
    nodeDict[6].right = nodeDict[9]
    nodeDict[3].left = nodeDict[2]
    nodeDict[3].right = nodeDict[5]

    nodeDict[9].left = nodeDict[8]
    nodeDict[9].right = nodeDict[10]

    nodeDict[2].left = nodeDict[1]
    nodeDict[5].left = nodeDict[4]
    nodeDict[8].left = nodeDict[7]
    root = nodeDict[rootValue]
    return root

def getCommonAncestor(path1, path2, find1, find2):
    if not (find1 and find2):
        return
    if not (path1 and path2):
        return
    length1 = len(path1)
    length2 = len(path2)
    size = min(length1, length2)
    findValue = None
    for i in range(size):
        if path1[i] == path2[i]:
            findValue = path1[i]
    return findValue

class Stack(object):

    def __init__(self):
        self.data = list()

    def empty(self):
        result = False if self.data else True
        return result

    def push(self, value):
        self.data.append(value)

    def pop(self):
        if self.empty():
            info = "stack is empty, it can not pop"
            print info
        else:
            self.data.pop()

    def top(self):
        if self.empty():
            info = "stack is empty, it can not get top element"
            print info
        else:
            return self.data[-1]

def getPathFromRoot(root, findValue, stack):
    if root is None:
        return False
    if root.data == findValue:
        stack.push(root.data)
        return True
    leftFlag = getPathFromRoot(root.left, findValue, stack)
    if leftFlag:
        stack.push(root.data)
        return True
    rightFlag = getPathFromRoot(root.right, findValue, stack)
    if not rightFlag:
        return False
    else:
        # 如果node节点在root节点的左子树或者右子树上,那么root就是祖先,需要加入到栈中
        stack.push(root.data)
        return True


def getNearestCommonAncestor(root, child1, child2):
    stack1 = Stack()
    stack2 = Stack()
    getPathFromRoot(root, child1, stack1)
    getPathFromRoot(root, child2, stack2)
    result = None
    while not stack1.empty() and not stack2.empty() and stack1.top() == stack2.top():
        result = stack1.top()
        stack1.pop()
        stack2.pop()
    return result




def process():
    data = [6, 3, 9, 2, 5, 8, 10, 1, 4, 7]
    root = buildTree(data, data[0])
    child1 = 1
    child2 = 5
    result = getNearestCommonAncestor(root, child1, child2)
    print result
    # find1, path1 = findNearestCommonAncestor(root, 1)
    # find2, path2 = findNearestCommonAncestor(root, 5)
    # result = getCommonAncestor(path1, path2, find1, find2)
    # print result


if __name__ == "__main__":
    process()

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/91788573