leetcode hot100 108. 将有序数组转换为二叉搜索树 medium 递归


常见的搜索树类型

  1. 性质:对于树中的每一个节点,左子树的所有节点值都小于该节点的值,右子树的所有节点值都大于该节点的值。
  2. 查找效率:查找、插入和删除操作的时间复杂度在 平均情况下 是 O(log n),最坏情况下是 O(n)(当树退化成链表时)。
  3. 应用场景:广泛用于需要有序数据访问的场景,如数据库的索引。
python 复制代码
    10
   /  \
  5    15
 / \     \
3   7     20
// 查找 7:从根节点 10 开始,比较 7 和 10,向左子树搜索;接着比较 7 和 5,向右子树搜索,最终找到节点 7。
  1. 特点:为了避免最坏情况的退化,平衡二叉搜索树通过某些规则保持树的平衡,保证树的高度不会太大,从而保证查找效率。
  2. 常见类型:
    AVL 树:通过旋转操作保持树的平衡。
    红黑树:通过颜色标记和旋转来保持平衡。
  3. 应用场景:用于要求较高查找效率的场景,如操作系统中的调度算法、数据库索引等。

搜索树的操作

搜索树支持多种操作,最常见的包括:

1. 查找(Search)

  • 从根节点开始,按照树的结构进行比较,寻找特定的值
  • 在二叉搜索树中,若当前值小于节点值,则继续查找左子树;若大于节点值,则查找右子树。

2. 插入(Insert)

  • 向树中插入一个新的值。首先找到合适的位置,再插入该节点
  • 在二叉搜索树中,插入值比节点值小则插入左子树,反之插入右子树。

3. 删除(Delete)

  • 从树中删除一个值。删除操作根据节点的子树情况分为三种情况:
  • 删除的节点是叶子节点(没有子节点)。
  • 删除的节点有一个子节点。
  • 删除的节点有两个子节点。此时需要找到节点的中序后继或中序前驱,并替换节点。

4. 遍历(Traversal)

  • 对树进行遍历,常见的遍历方法有:
    前序遍历(Pre-order)
    中序遍历(In-order):用于打印有序数据。
    后序遍历(Post-order)
    层序遍历(Level-order)

有序数组和二叉搜索树(BST)之间的关系

有序数组就像是 BST 的中序遍历结果。要把一个有序数组变成一棵平衡的 BST,最简单的方法就是:永远挑数组的正中间作为根节点。

  • BST 的特性:左边比根小,右边比根大。
  • 平衡的秘诀:如果选中间的数做根,那么它左边剩下的数和右边剩下的数,数量是几乎相等的。这样长出来的左右子树高度就一致,树也就"平衡"了。

递归三部曲实现

"分治法":

  1. 出口:数组为空(或者左边界大于右边界),返回 None。
  2. 操作:
    找到数组的中点 mid。
    用 nums[mid] 创建一个新的根节点。
  3. 递归:
    把左半部分交给递归函数,去生成左子树。
    把右半部分交给递归函数,去生成右子树。

mid = (left + right) // 2:如果数组长度是偶数,这个写法会选择中间偏左的那个。


空间复杂度: O(log⁡N)O(\log N)O(logN)。主要是递归栈的深度。每次都折半,所以树的高度一定是 log⁡N\log NlogN。
时间复杂度 :O(N)O(N)O(N)。我们需要把数组里的每个数都"摸"一遍,把它们变成节点。

其实就是"二分查找"的逆过程。

二分查找是在有序数组里"找"一个数,而这道题是把二分查找的每一个"中点"连起来变成了一棵树

如果不给"有序"数组呢?

如果数组是乱序的,必须先给它排序(O(Nlog⁡N)O(N \log N)O(NlogN)),然后再用这个方法构建。


答案可能不是唯一的。如果 n 是偶数,我们可以取数组正中间左边那个数作为根节点的值,也可以取数组正中间右边那个数作为根节点的值。下面代码取的是正中间右边那个数,即下标为 n/2的数(当 n 是偶数时)。

python 复制代码
// eg: nums=[−10,−3,0,5,9]
从数组正中间的数 nums[2]=0 开始,把数组一分为二,得到两个小数组:
左:[−10,−3]。
右:[5,9]。

//答案由三部分组成:
根节点:节点值为 nums[2]=0。
把 nums[2] 左边的 [−10,−3] 转换成一棵平衡二叉搜索树,作为答案的左儿子。这是一个和原问题相似的子问题,可以递归解决。
把 nums[2] 右边的 [5,9] 转换成一棵平衡二叉搜索树,作为答案的右儿子。这是一个和原问题相似的子问题,可以递归解决

// 递归边界:如果数组长度等于 0,返回空节点。
python 复制代码
# 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 sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:

        # 出口:数组为空(或者左边界大于右边界),返回 None。
        if not nums:
            return None

        m = len(nums) // 2
        left = self.sortedArrayToBST(nums[:m])
        left = self.sortedArrayToBST(nums[m+1:])

        return TreeNode(nums[m], left, right)
        
        
python 复制代码
# 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 sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:

        def dfs(left,right):
        
            # 这里的 left == right 对应 [left, right) 区间为空
            if left == right:
                return None
            
            m = (left + right) // 2
            
            # 先递归,再组装(自底向上)
            # 注意:右开区间,所以左边是 [left, m),右边是 [m + 1, right)
            left_child = dfs(left, m)   # 递归左区间
            right_child = dfs(m + 1, right)   # 递归右区间
            
            #结束递归,返回给主函数sortedArrayToBST-> Optional[TreeNode]:
            return TreeNode(nums[m], left_child, right_child)

        return dfs(0, len(nums))
        
相关推荐
sheeta19989 小时前
LeetCode 每日一题笔记 日期:2025.03.24 题目:2906.构造乘积矩阵
笔记·leetcode·矩阵
老鼠只爱大米14 小时前
LeetCode经典算法面试题 #295:数据流的中位数(双堆法、有序列表、平衡树等多种实现方案详解)
算法·leetcode·优先队列··数据流·中位数·java 面试题
x_xbx14 小时前
LeetCode:215. 数组中的第K个最大元素
数据结构·算法·leetcode
进击的荆棘16 小时前
优选算法——分治
数据结构·算法·leetcode·分治
木井巳16 小时前
【递归算法】找出所有子集的异或总和再求和
java·算法·leetcode·决策树·深度优先
Aaswk17 小时前
回溯算法的本质理解
c语言·算法·leetcode·力扣·剪枝
迷海18 小时前
力扣原题《分发糖果》,采用二分原则,纯手搓,待验证
c++·算法·leetcode
玛卡巴卡ldf18 小时前
【LeetCode 手撕算法】(普通数组)53-最大子数组和、56-合并区间、189-轮转数组、238-除了自身以外数组的乘积
数据结构·算法·leetcode
Sakinol#18 小时前
Leetcode Hot 100 ——动态规划part02
算法·leetcode·动态规划
Frostnova丶19 小时前
LeetCode 238 & 2906.构造乘积数组与乘积矩阵
算法·leetcode·矩阵