代码随想录算法训练营第十五天(二叉树篇)|Leetcode654最大二叉树,Leetcode617合并二叉树,Leetcode700二叉搜索树中的搜索,Leetcode98验证二叉搜索树

Leetcode 654 最大二叉树

题目链接: 最大二叉树

给定一个不含重复元素的整数数组,据此构建一棵最大二叉树,方法如下:

  1. 找出该数组中最大的元素,为其创建一个相应二叉树节点。该元素将该数组分割成两个部分。
  2. 从左部分中选取其中最大的元素,作为当前节点的左孩子节点
  3. 从右部分中选取其中最大的元素,作为当前节点的右孩子节点,重复上述操作直至处理完数组中所有元素。

思路: 整理上述流程,我们知道,我们需要不断找出数组片段中最大值,创建相应节点,并递归处理剩下的区间。

有了昨天处理 从中序遍历和后续遍历构造二叉树(Leetcode 106) 的经验,我们知道,传递区间最佳的方式不是再创建额外的数组,而是传递下标和原数组。因此此处我们采用传递下标的方式解决相应问题。

递归三部曲分析如下:

  1. 递归函数参数与返回值
    递归函数参数为数组整体,以及用于分割数组的相应下标。返回值为创建好的相应二叉树节点
  2. 递归终止条件:
    当给定区间为空时,终止遍历
  3. 每层递归操作:
    找出区间内最大值,利用该最大值将区间分割成两个部分。并将这两个部分的返回值分别作为当前节点的左右子节点。

具体代码实现

class Solution:
    def buildMaximumBinaryTree(self, nums: List[int], startIdx: int, endIdx: int) -> Optional[TreeNode]:
        # 由于坚持左闭右开区间,因此当起始下标大于等于终止下标时,停止继续向下递归。
        if startIdx >= endIdx:
            return

        # 找出给定区间内的最大值
        maxIdx, maxElement = startIdx, nums[startIdx]
        for i in range(startIdx, endIdx):
            if nums[i] > maxElement:
                maxIdx, maxElement = i, nums[i]

        root = TreeNode(maxElement)

        leftStartIdx = startIdx
        leftEndIdx = maxIdx
        rightStartIdx = maxIdx + 1
        rightEndIdx = endIdx

        if leftEndIdx - leftStartIdx > 0:
            root.left = self.buildMaximumBinaryTree(nums, leftStartIdx, leftEndIdx)
        if rightEndIdx - rightStartIdx > 0:
            root.right = self.buildMaximumBinaryTree(nums, rightStartIdx, rightEndIdx)

        return root

    def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
        # 坚持左闭右开区间
        root = self.buildMaximumBinaryTree(nums, 0, len(nums))
        return root

Leetcode 617 合并二叉树

题目链接: 合并二叉树

给定两棵二叉树,将其中的节点进行合并,返回合并后二叉树的根节点。

Example1:

    1           2           3
   / \         / \         / \
  3   2   +   1   3   =   4   5
 /             \   \     / \   \
5               4   7   5   4   7

当对应节点均存在时,合并后节点的值相当于对应节点值之和
当对应节点存在一个时,合并后节点的值相当于存在的节点值

思路: 合并二叉树时,我们可以在其中一棵二叉树中对节点的值原地进行修改,完成修改后,直接返回对应二叉树的根节点即可。

通过递归三部曲进行分析:

  1. 递归函数参数以及返回值:
    递归函数参数为当前正在遍历的两棵二叉树的对应节点,返回值应该为两棵二叉树合并后的节点
  2. 递归终止条件
    正在遍历的两棵二叉树的相应节点均为空时,终止递归操作。
  3. 每层递归操作
    若两棵二叉树的相应节点均存在,则将节点值相加,创建一个新节点。若仅一棵二叉树的相应节点存在,则在其中一棵二叉树的节点上原地进行修改。

具体代码实现

class Solution:
    def merge(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        # 对应节点均不存在,返回空
        if root1 is None and root2 is None:
            return

        # 两个节点均存在,将节点值相加
        if root1 and root2:
            root1.val += root2.val
            root1.left = self.merge(root1.left, root2.left)
            root1.right = self.merge(root1.right, root2.right)
            return root1

        # 返回存在的相应节点
        if root1:
            return root1

        return root2

    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        return self.merge(root1, root2)

Leetcode 700 二叉搜索树中的搜索

题目链接: 二叉搜索树中的搜索

在一棵给定的二叉搜索树中,检索给定的值是否出现过。若给定的值在二叉树中出现过则返回相应节点,否则返回空

思路: 首先复习二叉搜索树的概念。
二叉搜索树,即为根节点严格大于左子树中的所有节点,严格小于右子树中所有节点,且左右子树均递归地符合这一要求的一类二叉树。通过二叉搜索树搜索特定的值,时间复杂度为 O(logn)

利用递归三部曲进行分析:

  1. 递归函数参数与返回值:
    递归函数参数为当前遍历的节点以及待查找的目标值,返回值为相应的二叉树节点
  2. 递归终止条件:
    当前节点为空时,返回空节点,终止递归操作。
  3. 每层递归操作:
    比较当前节点的值与目标值,若相等,则返回相应节点,若不相等,则继续深度递归。

具体代码实现

# 递归法
class Solution:
    def search(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root is None:
            return

        if root.val > val:
            return self.search(root.left, val)

        if root.val < val:
            return self.search(root.right, val)

        return root

    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        return self.search(root, val)
# 迭代法
class Solution:
    def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        from collections import deque

        if root is None:
            return

        myQueue = deque()
        myQueue.append(root)

        while myQueue:
            node = myQueue.popleft()

            if node.val == val:
                return node

            # 利用二叉搜索树中的特性,将相应节点加入到队列中
            if node.val > val and node.left:
                myQueue.append(node.left)

            if node.val < val and node.right:
                myQueue.append(node.right)

        return

Leetcode 98 验证二叉搜索树

题目链接: 验证二叉搜索树

给定一棵二叉树,判断该二叉树是否为二叉搜索树。

思路: 本题中一个常见的误区是,直接尝试使用递归法,通过左右子树是否满足二叉搜索树的条件,来判断以当前节点为根节点的二叉树是否为二叉搜索树。然而这种思路并不能够处理以下的情况:

        5
       / \
      4   6
         / \
        3   7

由于 3 < 5,因此该二叉树不是二叉搜索树。

再回忆二叉树的特性,二叉树的根节点大于左子树中的所有节点,小于右子树中的所有节点。因此,我们可以尝试通过中序遍历,获取当前二叉树的数组。若当前二叉树确实是二叉搜索树,则该数组应该是严格递增的。因此,我们可以通过判断当前数组是否严格递增,来判断当前二叉树是否为二叉搜索树。

具体代码实现

class Solution:
    def inorderTraverse(self, cur: Optional[TreeNode]) -> List[int]:
        result = []
        myStack = []

        if cur is None:
            return result

        myStack.append([cur, False])

        while myStack:
            node, visited = myStack.pop()
            if visited:
                result.append(node.val)
                continue

            if node.right:
                myStack.append([cur.right, False])

            myStack.append([cur, True])

            if node.left:
                myStack.append([cur.left, False])

        return result

    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        inorder = self.inorderTraverse(root)

        # 验证中序数组是否严格单调递增
        for i in range(1, len(inorder)):
            if inorder[i] <= inorder[i-1]:
                return False

        return True
posted @ 2025-08-22 20:59  雪痕春风天音九重色  阅读(11)  评论(0)    收藏  举报