算法-二叉树

20.验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
    #递归法1
    class Solution:
        def isValidBST(self,root:TreeNode):
            tmp = []
    
            def traverse(root:TreeNode):
                if not root:
                    return
                traverse(root.left)
                tmp.append(root.val)
                traverse(root.right)
    
            def is_sorted(nums):
                for i in range(1,len(nums)):
                    if nums[i] <= nums[i - 1]:
                        return False
                return True
            traverse(root)
    
            return is_sorted(tmp)
    # 递归法2
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            # 规律: BST的中序遍历节点数值是从小到大.
            self.cur = -float('inf')
            def isValidBST(root):
                if not root:
                    return True
                is_left_v = isValidBST(root.left)
                if self.cur < root.val:
                    self.cur = root.val
                else:
                    return False
                is_right_v = isValidBST(root.right)
                return is_left_v and is_right_v
            return isValidBST(root)
    #迭代法
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            stack = []
            cur = root
            pre = None
            while cur or stack:
                if cur:
                    stack.append(cur)
                    cur = cur.left
                else:
                    cur = stack.pop()
                    if pre and cur.val <= pre.val:
                        return False
                    pre = cur
                    cur = cur.right
            return True
    

    21.二叉搜索树的最小绝对差

  • 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。

    #递归
    class Solution:
        def getMinimumDifference(self, root: TreeNode) -> int:
            res = []
            r = float('inf')
            def buildList(root:TreeNode):
                if not root:
                    return
                buildList(root.left)
                res.append(root.val)
                buildList(root.right)
    
            buildList(root)
            for i in range(len(res) - 1):
                r = min(abs(res[i] - res[i + 1]),r)
            return r
    #迭代中序
    class Solution:
        def getMinimumDifference(self, root: TreeNode) -> int:
            stack = []
            cur = root
            pre = None
            res = float('inf')
            while stack or cur:
                if cur:
                    stack.append(cur)
                    cur = cur.left
                else:
                    cur = stack.pop()
                    if pre:
                        res = min(res,cur.val - pre.val)
                    pre = cur
                    cur = cur.right
            return res

    22.二叉搜索树中的众数

    #递归法
    class Solution:
        def __init__(self):
            self.pre = TreeNode()
            self.count = 0
            self.max_count = 0
            self.res = []
    
        def findMode(self,root:TreeNode):
            if not root:return None
            self.searchBST(root)
            return self.res
    
        def searchBST(self,cur:TreeNode):
            if not cur:
                return None
            self.searchBST(cur.left)
            if not self.pre:
                self.count = 1
            elif self.pre.val == cur.val:
                self.count += 1
            else:
                self.count = 1
            self.pre = cur
    
            if self.count == self.max_count:
                self.res.append(cur.val)
    
            if self.count > self.max_count:
                self.max_count = self.count
                self.res = [cur.val]
            self.searchBST(cur.right)
    #迭代法
    class Solution:
        def findMode(self, root: TreeNode):
            stack = []
            cur = root
            pre = None
            maxcount = count = 0
            res = []
            while cur or stack:
                if cur:
                    stack.append(cur)
                    cur = cur.left
                else:
                    cur = stack.pop()
                    if pre is None:
                        count = 1
                    elif pre.val == cur.val:
                        count += 1
                    else:
                        count = 1
    
                    if count == maxcount:
                        res.append(cur.val)
                    if count > maxcount:
                        maxcount = count
                        res.clear()
                        res.append(cur.val)
    
                    pre = cur
                    cur = cur.right
            return res

    23.二叉树的最近公共祖先

#递归法
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root or root == p or root == q:return root

        left = self.lowestCommonAncestor(root.left,p,q)
        right = self.lowestCommonAncestor(root.right,p,q)

        if not left:return right
        if not right:return left

        return root

24.二叉搜索树的最近公共祖先

#递归法
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if root.val > p.val and root.val > q.val:
            return self.lowestCommonAncestor(root.left, p, q)
        if root.val < p.val and root.val < q.val:
            return self.lowestCommonAncestor(root.right, p, q)
        return root
#迭代法
class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        while True:
            if root.val > p.val and root.val > q.val:
                root = root.left
            elif root.val < p.val and root.val < q.val:
                root = root.right
            else:
                return root

25.二叉搜索树中的插入操作

#递归法
class Solution:
    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        if not root:
            return TreeNode(val)
        if val < root.val:
            # 将val插入至当前root的左子树中合适的位置
            # 并更新当前root的左子树为包含目标val的新左子树
            root.left = self.insertIntoBST(root.left, val)
        if root.val < val:
            # 将val插入至当前root的右子树中合适的位置
            # 并更新当前root的右子树为包含目标val的新右子树
            root.right = self.insertIntoBST(root.right, val)
        return root
#迭代法
class Solution:
    def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
        if not root:
            return TreeNode(val)
        cur = root
        while cur:
            if val < cur.val:
                if not cur.left:
                    cur.left = TreeNode(val)
                    break
                else:
                    cur = cur.left
            else:
                if not cur.right:
                    cur.right = TreeNode(val)
                    break
                else:
                    cur = cur.right
        return root

26.删除二叉搜索树中的节点

#递归法
class Solution:
    def deleteNode(self, root: TreeNode, key: int):
        # 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if not root:return root
        if root.val == key:
            # 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if not root.left and not root.right:
                del root
                return None
            # 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            if not root.left and root.right:
                tmp = root
                root = root.right
                del tmp
                return root
            # 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            if root.left and not root.right:
                tmp = root
                root = root.left
                del tmp
                return root
            # 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            else:
                v = root.right
                while v.left:
                    v = v.left
                v.left = root.left
                tmp = root
                root = root.right
                del tmp
                return root
        if root.val > key:root.left = self.deleteNode(root.left,key)
        if root.val < key: root.right = self.deleteNode(root.right, key)
        return root

27.修剪二叉搜索树

#递归法
class Solution:
    def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
        if not root:return None

        if root.val < low:
            # 若当前root节点小于左界:只考虑其右子树,用于替代更新后的其本身,抛弃其左子树整体
            return self.trimBST(root.right,low,high)
        if high < root.val:
            # 若当前root节点大于右界:只考虑其左子树,用于替代更新后的其本身,抛弃其右子树整体
            return self.trimBST(root.left, low, high)
        if low <= root.val <= high:
            root.left = self.trimBST(root.left,low,high)
            root.right = self.trimBST(root.right, low, high)
            # 返回更新后的剪枝过的当前节点root
            return root

28.将有序数组转换为二叉搜索树

#递归法
class Solution:
    def sortedArrayToBST(self, nums) -> TreeNode:
        '''
        构造二叉树:重点是选取数组最中间元素为分割点,左侧是递归左区间;右侧是递归右区间
        必然是平衡树
        左闭右闭区间
        '''
        # 返回根节点
        root = self.traversal(nums,0,len(nums)-1)
        return root
    def traversal(self,nums,left,right):
        if left > right:
            return None
        # 确定左右界的中心,防越界
        mid = left + (right - left) // 2
        # 构建根节点
        mid_root = TreeNode(nums[mid])
        # 构建以左右界的中心为分割点的左右子树
        mid_root.left = self.traversal(nums,left,mid - 1)
        mid_root.right = self.traversal(nums, mid + 1, right)

        # 返回由被传入的左右界定义的某子树的根节点
        return mid_root

29.把二叉搜索树转换为累加树

class Solution:
    def convertBST(self, root: TreeNode) -> TreeNode:
        def dfs(root):
            if root:
                dfs(root.right)
                self.total += root.val
                root.val = self.total
                dfs(root.left)

        self.total = 0
        dfs(root)
        return root

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值