ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【树】力扣669:修剪二叉搜索树

2022-07-23 11:05:13  阅读:131  来源: 互联网

标签:right cur 669 二叉 力扣 val low root left


给你二叉搜索树的根节点 root,同时给定最小边界 low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在 [low, high] 中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例:

image
输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]

二叉搜索树的特点:node.left < node < node.right

参考:https://leetcode.cn/problems/trim-a-binary-search-tree/solution/python3di-gui-die-dai-by-pinkman-r-nvd8/

递归

对于二叉数的递归,要想清楚当前的 root 结点需要干什么
image

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return
        # 找到符合区间范围的结点
        if root.val < low: # 如果当前结点的值小于 low:递归右子树,剪裁后重新赋值给当前结点 root
            root = self.trimBST(root.right, low, high)
        elif root.val > high: # 如果当前结点的值大于 high:递归左子树,剪裁后重新赋值给当前结点 root
            root = self.trimBST(root.left, low, high)
        else: # 结点值在区间范围内:将下一层处理完左子树的结果赋给 root.left,处理完右子树的结果赋给 root.right
            root.left = self.trimBST(root.left, low, high)
            root.right = self.trimBST(root.right, low, high)

        return root

注意,调用本身这个函数加上 self.

如果不喜欢用 self,可以定义一个辅函数,在主函数中直接运行辅函数。

class Solution(object):
    def trimBST(self, root, L, R):
        def trim(node):
            if not node:
                return None
            elif node.val > R:
                return trim(node.left)
            elif node.val < L:
                return trim(node.right)
            else:
                node.left = trim(node.left)
                node.right = trim(node.right)
                return node

        return trim(root)

时间复杂度:O(N),其中 N 是给定的树的全部结点。最多每个结点访问一次。

空间复杂度:O(N),即使没有明确使用任何额外的内存,在最糟糕的情况下,递归调用的栈可能与结点数一样大。

迭代

在进行二叉树剪枝的时候,可以分为三步:

  • 将 root 移动到 [low, high] 范围内
while root and (root.val < low or root.val > high):
    if root.val < low:
        root = root.right
    else:
        root = root.left
  • 剪枝左子树
cur = root
while cur:
    while cur.left and cur.left.val < low:
        cur.left = cur.left.right
    cur = cur.left
  • 剪枝右子树
cur = root
while cur:
    while cur.right and cur.right.val > high:
        cur.right = cur.right.left
    cur = cur.right

总体代码:

class Solution:
    def trimBST(self, root: Optional[TreeNode], low: int, high: int) -> Optional[TreeNode]:
        if not root:
            return
        # 根结点 root 的值不在区间内:向下找到适合的结点作为新的根结点 root,想象为新树
        while root and (root.val < low or root.val > high):
            if root.val < low:
                root = root.right
            else:
                root = root.left
        # 结点值在区间内:1. 左子树剪枝
        cur = root
        while cur:
            while cur.left and cur.left.val < low:
                cur.left = cur.left.right
            cur = cur.left
        # 结点值在区间内:2. 右子树剪枝
        cur = root
        while cur:
            while cur.right and cur.right.val > high:
                cur.right = cur.right.left
            cur = cur.right
        return root

标签:right,cur,669,二叉,力扣,val,low,root,left
来源: https://www.cnblogs.com/Jojo-L/p/16511133.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有