zoukankan      html  css  js  c++  java
  • 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
    

      

  • 相关阅读:
    Combine 框架,从0到1 —— 4.在 Combine 中使用计时器
    Combine 框架,从0到1 —— 4.在 Combine 中使用通知
    Combine 框架,从0到1 —— 3.使用 Subscriber 控制发布速度
    Combine 框架,从0到1 —— 2.通过 ConnectablePublisher 控制何时发布
    使用 Swift Package Manager 集成依赖库
    iOS 高效灵活地配置可复用视图组件的主题
    构建个人博客网站(基于Python Flask)
    Swift dynamic关键字
    Swift @objcMembers
    仅用递归函数操作逆序一个栈(Swift 4)
  • 原文地址:https://www.cnblogs.com/chaojunwang-ml/p/11355359.html
Copyright © 2011-2022 走看看