字节跳动面试题/《程序员代码面试指南.二叉树中的最大搜索二叉子树

1.题目描述

给定一棵二叉树的头节点head,已知其中所有节点的值都不一样,找到含有节点最多的搜索二叉子树,并返回这棵子树的头节点。例如,下图中,右树就是左树的最大搜索子树。
图

2.解题思路

首先解释一下什么是最大搜索子树,就是二叉搜索树,任意节点的值必定大于左子树的最大值,小于右子树的最小值,且左右子树都是二叉搜索树。

所以很容易想到使用递归来进行解题。

1.整个过程使用后序遍历

2.遍历到当前节点记为cur时,先遍历cur的左子树收集4个信息,分别是左子树上最大搜索二叉子树的头节点(lBST)、节点数(lSize)、最小值(lMin)和最大值(lMax)。再遍历cur的右子树收集4个信息,分别是右子树上最大搜索二叉子树的头节点(rBST)、节点数(rSize)、最小值(rMin)和最大值(rMax)

3.根据步骤2所收集的信息,判断是否满足搜索子树的定义(1,要保证返回的节点lBST和递归时的节点left是一个,rBST也是如此,并且当前节点的值满足大于左子树的最大值,小于右子树的最小值),如果满足就返回cur节点,如果不满足就返回lBST和rBST中子节点数多的那一个

参考:https://www.cnblogs.com/yangtong/p/6687078.html

参考:https://blog.csdn.net/gaoyueace/article/details/90404985

3.代码实现

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def main(self):
        root = self.buidTree()
        res = self.posOrder(root,[0,0,0])
        print res.val
    def buidTree(self):
        root = TreeNode(6)
        root.left = TreeNode(1)
        root.right = TreeNode(12)
        root.left.left = TreeNode(0)
        root.left.right = TreeNode(3)
        root.right.left = TreeNode(10)
        root.right.left.left = TreeNode(4)
        root.right.left.left.left = TreeNode(2)
        root.right.left.left.right = TreeNode(5)
        root.right.left.right = TreeNode(14)
        root.right.left.right.left = TreeNode(11)
        root.right.left.right.right = TreeNode(15)
        root.right.right = TreeNode(13)
        root.right.right.left = TreeNode(20)
        root.right.right.right = TreeNode(16)
        return root

    def posOrder(self, root, record):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            record[0] = 0
            record[1] = float("inf")
            record[2] = float("-inf")
            return None
        value = root.val
        left = root.left
        right = root.right

        lBST = self.posOrder(root.left,record)
        lSize = record[0]
        lMin = record[1]
        lMax = record[2]

        rBST = self.posOrder(root.right, record)
        rSize = record[0]
        rMin = record[1]
        rMax = record[2]


        # 保存当前子树中的最大值与最小值,不是只保存左子树的最大值与右子树的最小值
        record[1] = min(lMin,value)
        record[2] = max(rMax,value)
        # 只有当左右两个子树的根节点是当前节点的左右子节点,当前节点才能作为根节点加入
        if (not left and not lBST and not right and not rBST) or (left.val == lBST.val and right.val == rBST.val) and lMax < value and value < rMin:
            record[0] = lSize + rSize + 1
            return root
        # 若左右子树不能合并,返回当前最长的那个子树的根节点
        else:
            record[0] = max(lSize,rSize)
            if lSize > rSize:
                return lBST
            else:
                return rBST
s=Solution()
s.main()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值