• Leetcode-树


    98. 验证二叉搜索树 https://leetcode-cn.com/problems/validate-binary-search-tree/

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

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

    节点的左子树只包含小于当前节点的数。
    节点的右子树只包含大于当前节点的数。
    所有左子树和右子树自身必须也是二叉搜索树。

    解:

    中序遍历二叉排序树,判断得到的数组是否是升序。

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            inorder = self.inorder(root)
            return inorder == sorted(set(inorder))  # 这里要注意判重
            
        def inorder(self, root):
            if root is None:
                return []
            return self.inorder(root.left) + [root.val] + self.inorder(root.right)
    

      

    但是这个效率是相对较低的,想办法改进一下,不用完整保留中序遍历的结果,只需要比较中序遍历时当前节点和前驱节点即可

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            self.prev = None
            return self.helper(root)
        
        def helper(self, root):
            if root is None:
                return True
            if not self.helper(root.left):  # 如果左子树不是二叉搜索树,那root也不是
                return False
            if self.prev and self.prev.val >= root.val: # 如果左子树是二叉搜索树,比较root和其前驱节点值,如果前驱大,root不是二叉搜索树
                return False
            self.prev = root  # 如果满足root比前驱大,下面去检查右子树,在此之前要先把前驱节点更新为root
            return self.helper(root.right)
    

      

    直接递归来判断

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            if root is None:
                return True
            if root.left is None and root.right is None:
                return True
       
            flag = True
            if root.left: 
                if not self.isValidBST(root.left):
                    flag = False
                # 左子树的最大,一直向右即可
                l = root.left
                while l.right:
                    l = l.right
                if root.val <= l.val:
                    flag = False
                    
            if root.right:    
                if not self.isValidBST(root.right):
                    flag = False
                # 右子树的最小,一直向左即可
                r = root.right
                while r.left:
                    r = r.left
                if root.val >= r.val:
                    flag = False
            return flag
    

      

    这个递归写的也是比较冗余的,有很多重复搜索。再简化一下,每次都把节点和其上下界比较(如果有的话)。

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def isValidBST(self, root: TreeNode) -> bool:
            return self.isValid(root)
        
        def isValid(self, root, lower=float('-inf'), upper=float('inf')):
            if root is None:
                return True
            val = root.val
            if lower is not None and val <= lower:
                return False
            if upper is not None and val >= upper:
                return False
            if not self.isValid(root.left, lower, val):
                return False
            if not self.isValid(root.right, val, upper):
                return False
            return True
    

      

    235. 二叉搜索树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

    最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    说明:

    所有节点的值都是唯一的。

    p、q 为不同节点且均存在于给定的二叉搜索树中。

    解:

    迭代,从根节点往下,如果根节点比两个节点都大,说明两个节点在根节点的左子树中;如果根节点比两个节点都小,说明两个节点在根节点的右子树中。更新根节点即可。

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
            if not root:
                return None
            if root.left is None and root.right is None:
                return root
            ans = root
            while ans:
                if ans.val < p.val and ans.val < q.val:
                    ans = ans.right
                elif ans.val > p.val and ans.val > q.val:
                    ans = ans.left
                else:
                    return ans
    

      

    递归实现,空间复杂度O(N)。这题其实没必要用递归

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    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.right, p, q)  # p、q比root都大,需要去root右子树查找
            if root.val > p.val and root.val > q.val:
                return self.lowestCommonAncestor(root.left, p, q)
         return root

      

    236.二叉树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    解:

    递归,从根节点开始向下,如果root就是p或者q,那么公共祖先就是root,否则的话分别去左右子树查找p和q,如果p、q都在左子树,递归的去左子树向下查找;如果p、q都在右子树,递归的去右子树查找;如果p、q各在一边,那么root

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
            if root is None or root is q or root is p:
                return root
            left = self.lowestCommonAncestor(root.left, p, q)  # 分别去左右子树查找p和q
            right = self.lowestCommonAncestor(root.right, p, q)
            if left is None:  # 如果p、q都不在左子树,返回右子树的查找结果
                return right
            elif right is None:  # 如果p、q都不在右子树,返回左子树的查找结果
                return left
            return root   # 如果p和q各在左右一边,公共祖先就是当前root
    

      

    使用父指针迭代,找出 p 和 q 的各自到根节点的路径。如果每个节点都有父指针,可以从 p 和 q 返回以获取它们的祖先。在这个遍历过程中,得到的第一个公共节点是 LCA 节点。可以在遍历树时将父指针保存在字典中。

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
            parent = {root: None}
            stack = [root]
            
            # 只要没有把p、q都找到,就继续向下遍历树,继续找
            while p not in parent or q not in parent:
                node = stack.pop()
                
                if node.left:
                    parent[node.left] = node
                    stack.append(node.left)
                    
                if node.right:
                    parent[node.right] = node
                    stack.append(node.right)
                    
            ancestors = set()  # 按父指针遍历p的祖先
            while p:
                ancestors.add(p)
                p = parent[p]
            
            while q not in ancestors:  # 找p、q公共的祖先
                q = parent[q]
            return q
    

      

  • 相关阅读:
    注册事件为何无效,没有触发? AUTOPOSTBACK已经设置为TRUE
    不使用web服务实现文本框自动完成扩展
    实现一个搜索功能思路
    QT练习3:QT数字和滚动条关联
    Qt 显示图片 放大 缩小 移动
    QT 的信号与槽机制介绍
    一个有很多QT免费应用例程的网站
    yafeilinux.com的开源项目非常好的东西
    vector的用法
    C语言实现获取LINUX当前时间
  • 原文地址:https://www.cnblogs.com/chaojunwang-ml/p/11355359.html
Copyright © 2020-2023  润新知