代码随想录day20:二叉树05(最大二叉树,合并二叉树,二叉搜索树中的搜索,验证二叉搜索树)

1. 最大二叉树(leetcode 654)

这题和我们day17 二叉树04里面的用后序中序数组构造二叉树的思路基本一模一样。

同样也是用我们的递归法。先找出最大值,然后把最大值设置为当前节点,然后用最大值把数组分为左右两部分,然后对左右两部分进行递归。代码如下。

class Solution:
    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        if len(nums) == 0:
            return None
        max_val = max(nums)
        position = nums.index(max_val)
        root = TreeNode(max_val)

        left_nums = nums[:position]
        right_nums = nums[position+1:]

        root.left = self.constructMaximumBinaryTree(left_nums)
        root.right = self.constructMaximumBinaryTree(right_nums)

        return root

2. 合并二叉树(leetcode 617)

这题前中后序遍历都可以的,没啥限制,因为都要遍历到也都要处理到。

我们以前序遍历为例,这边过一下递归三部曲:

1.确认参数和返回值。参数就是两棵树相同位置的根节点,返回值就是合并的当前位置根节点。

2. 确认终止条件。当两棵树都没有,终止为None。当其中一颗树没有,则直接返回另一棵树。像这种有两棵树的题,我们一定要考虑好其中一颗树为空的情况,做到面面俱到。

3. 确认单层递归逻辑。就按中左右的顺序遍历递归就好。

class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root1 and not root2:
            return None
        if not root1: return root2
        if not root2: return root1

        value1 = root1.val
        value2 = root2.val
        current = value1 + value2
        root = TreeNode(current)

        root.left = self.mergeTrees(root1.left, root2.left)
        root.right = self.mergeTrees(root1.right, root2.right)

        return root

这题不太好用stack迭代写,因为有的节点是只有一个树有的,我们不太好处理。递归我们才能统一处理。 

当然我们也可以用queue的方式写,在root1这颗树上根据root2这颗树的节点来改动,这样写更省空间,时间复杂度是一样的。这应该是本题比较好的一个写法。

class Solution:
    def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode:
        if not root1: 
            return root2
        if not root2: 
            return root1

        queue = deque()
        queue.append(root1)
        queue.append(root2)

        while queue: 
            node1 = queue.popleft()
            node2 = queue.popleft()
            # 更新queue
            # 只有两个节点都有左节点时, 再往queue里面放.
            if node1.left and node2.left: 
                queue.append(node1.left)
                queue.append(node2.left)
            # 只有两个节点都有右节点时, 再往queue里面放.
            if node1.right and node2.right: 
                queue.append(node1.right)
                queue.append(node2.right)

            # 更新当前节点. 同时改变当前节点的左右孩子. 
            node1.val += node2.val
            if not node1.left and node2.left: 
                node1.left = node2.left
            if not node1.right and node2.right: 
                node1.right = node2.right

        return root1

3. 二叉搜索树中的搜索(leetcode 700)

非常简单的一道题,给定了binary tree,我们直接利用binary tree的特性递归就好了。

1. 参数和返回值:参数为节点和value,返回值为满足目标的树

2. 终止条件:若为空节点,就代表走到头了,返回None

3. 单层递归逻辑,按照binary tree的特性二分往下递归就好。

class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if not root:
            return None
        current_val = root.val
        if root.val == val: return root
        if root.val > val: return self.searchBST(root.left, val)
        if root.val < val: return self.searchBST(root.right, val)

同样的这题我们也可以用stack或者直接用节点来迭代。因为我们想要利用二叉搜索树得到特性,所以我们不能使用queue来层序遍历。

class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        while root:
            if val < root.val: root = root.left
            elif val > root.val: root = root.right
            else: return root
        return None

 4. 验证二叉搜索树(leetcode 98)

这道题我们要先确认用什么遍历方式。

要知道在中序遍历下,输出的二叉搜索树节点的数值是有序序列。这是个很重要的特性,左中右从小到达排呗。所以我们只需要验证中序序列是否递增就可以了。

class Solution:
    def traversal(self, root):
        if not root:
            return
        self.traversal(root.left)
        self.nums.append(root.val)
        self.traversal(root.right)

    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        self.nums = []
        self.traversal(root)
        for i in range(1,len(self.nums)):
            if self.nums[i] <= self.nums[i-1]:
                return False
        return True
        

这是一个很讨巧的方法,但我们也是要记住这层中序和二叉搜索树的关系的。

同时我们也可以用迭代法,中序迭代,中间遇到更大的值,直接return False。这个方法会省点时间,因为平均情况是不用遍历完整个树的。

class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        stack = []
        cur = root
        pre = None  # 记录前一个节点
        while cur is not None or len(stack) > 0:
            if cur is not None:
                stack.append(cur)
                cur = cur.left  # 左
            else:
                cur = stack.pop()  # 中
                if pre is not None and cur.val <= pre.val:
                    return False
                pre = cur  # 保存前一个访问的结点
                cur = cur.right  # 右
        return True
        

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值