当前位置: 首页 > news >正文

【LeetCode】动态规划—95. 不同的二叉搜索树 II(附完整Python/C++代码)

动态规划—95. 不同的二叉搜索树 II

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
      • 二叉搜索树的性质:
    • 2. 理解问题和递推关系
      • 递归构造思想:
      • 状态定义:
      • 递推公式:
      • 终止条件:
    • 3. 解决方法
      • 递归 + 动态规划方法:
      • 伪代码:
      • 特别注意:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释
  • C++代码
      • C++代码解释
  • 总结

题目描述

在这里插入图片描述

前言

不同的二叉搜索树 II 是一个要求构造出所有可能的 二叉搜索树(BST) 的问题。给定一个整数 n,我们需要构造出由 1n 为节点的所有不同形态的二叉搜索树,并返回这些树的根节点列表。该问题与 不同的二叉搜索树 I 不同的是,不仅要求计算不同二叉搜索树的数量,还需要输出所有可能的二叉搜索树的具体结构。


基本思路

1. 问题定义

给定一个整数 n,构造所有包含 1n 的不同二叉搜索树,并返回这些树的根节点列表。每个二叉搜索树的节点只能使用一次,且必须保持 二叉搜索树 的性质。

二叉搜索树的性质:

  • 左子树的所有节点值都小于根节点值。
  • 右子树的所有节点值都大于根节点值。

2. 理解问题和递推关系

递归构造思想:

我们可以使用递归的方法来构造二叉搜索树。对于任意一个 i,它可以作为根节点,1i-1 组成它的左子树,i+1n 组成它的右子树。递归构造左子树和右子树,并将不同的子树组合起来。

状态定义:

  1. 对于区间 [start, end],构造由该区间组成的所有二叉搜索树。
  2. 递归地将每个数字作为根节点,左子树由 [start, i-1] 构造,右子树由 [i+1, end] 构造。
  3. 组合所有左子树和右子树,形成不同的二叉搜索树。

递推公式:

  1. 对于每个根节点 i,构造左子树 generateTrees(start, i-1) 和右子树 generateTrees(i+1, end)
  2. 将左右子树的所有组合与根节点 i 连接,形成不同的树形结构。

终止条件:

  • start > end 时,返回 None,表示当前区间不能构成任何子树。

3. 解决方法

递归 + 动态规划方法:

  1. 定义递归函数 generateTrees(start, end) 来构造 [start, end] 范围内的所有二叉搜索树。
  2. 对于每一个 i 作为根节点,递归构造左子树和右子树,并将其组合。
  3. 最终返回所有构造的树。

伪代码:

function generateTrees(start, end):if start > end:return [None]all_trees = []for i from start to end:# 构造左子树和右子树left_trees = generateTrees(start, i-1)right_trees = generateTrees(i+1, end)# 组合左右子树与根节点for each left in left_trees:for each right in right_trees:root = new TreeNode(i)root.left = leftroot.right = rightall_trees.append(root)return all_trees

特别注意:

  • 递归调用会确保每个节点 i 都尝试作为根节点,并且分别生成左右子树。最终所有树形结构都被记录在结果列表中。

4. 进一步优化

  • 缓存递归结果:可以用备忘录的方式存储已经计算过的子树组合,避免重复计算,进一步优化效率。

5. 小总结

  • 问题思路:利用递归和分治的思想构造出所有二叉搜索树的结构,确保每个节点都作为一次根节点,并递归构造左右子树。
  • 时间复杂度:时间复杂度较高,因每次递归会构造不同的树形结构,复杂度为 超指数级别

以上就是不同的二叉搜索树 II问题的基本思路。


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 generateTrees(self, n: int) -> list[TreeNode]:if n == 0:return []# 递归函数,生成从start到end的所有二叉搜索树def generateTrees(start, end):if start > end:return [None]  # 返回一个空树all_trees = []  # 存储所有可能的二叉搜索树for i in range(start, end + 1):# 构造左子树和右子树left_trees = generateTrees(start, i - 1)right_trees = generateTrees(i + 1, end)# 组合所有的左子树和右子树for left in left_trees:for right in right_trees:root = TreeNode(i)  # 以i作为根节点root.left = leftroot.right = rightall_trees.append(root)return all_treesreturn generateTrees(1, n)

Python代码解释

  1. 定义递归函数generateTrees(start, end) 用于生成从 startend 所有不同的二叉搜索树。
  2. 递归构造:对于每个 i 作为根节点,递归构造左右子树的所有可能组合。
  3. 返回结果:最终返回所有可能的树形结构的根节点列表。

C++代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<TreeNode*> generateTrees(int n) {if (n == 0) return {};// 递归函数,生成从start到end的所有二叉搜索树return generateTrees(1, n);}vector<TreeNode*> generateTrees(int start, int end) {if (start > end) return {nullptr};  // 返回一个空树vector<TreeNode*> all_trees;  // 存储所有可能的二叉搜索树for (int i = start; i <= end; ++i) {// 构造左子树和右子树vector<TreeNode*> left_trees = generateTrees(start, i - 1);vector<TreeNode*> right_trees = generateTrees(i + 1, end);// 组合所有的左子树和右子树for (TreeNode* left : left_trees) {for (TreeNode* right : right_trees) {TreeNode* root = new TreeNode(i);  // 以i作为根节点root->left = left;root->right = right;all_trees.push_back(root);}}}return all_trees;}
};

C++代码解释

  1. 定义递归函数generateTrees(start, end) 用于生成从 startend 所有不同的二叉搜索树。
  2. 递归构造:对于每个 i 作为根节点,递归构造左右子树的所有可能组合。
  3. 返回结果:最终返回所有可能的树形结构的根节点列表。

总结

  • 核心思想:通过递归和分治的思想,将问题分解为左右子树的组合问题。每个节点都可以作为根节点,递归构造其左子树和右子树,再组合这些树形结构。
  • 复杂度分析:由于需要构造所有可能的树,时间复杂度较高,是 超指数级别 的问题。这类问题适合使用动态规划或递归解决,但无法避免高复杂度。
  • 递归的应用:本问题是递归和分治思想的典型应用,尤其适合解决树形结构的构造问题。

http://www.mrgr.cn/news/48992.html

相关文章:

  • javaweb笔记汇总
  • 华为云ECS部署DR模式的LVS
  • 【分布式微服务云原生】 探索SOAP协议:简单对象访问协议的深度解析与实践
  • windows C++-轻量级任务
  • 大模型生图安全疫苗注入赛题解析(DataWhale组队学习)
  • R语言统计分析——折线图
  • 自注意力机制self-attention中QKV矩阵的含义
  • 2025届保研-优营率0%上岸C9
  • C++面试速通宝典——24
  • 基于SpringBoot+Vue的陶怡居茶铺管理系统设计实现(协同过滤算法)
  • 实践体验密集小目标检测,以小麦麦穗颗粒为基准,基于嵌入式端超轻量级模型LeYOLO全系列【n/s/m/l】参数模型开发构建智能精准麦穗颗粒检测计数系统
  • 231水果滑块喜+1
  • g_strdup_printf
  • PostgreSql的备份和升级
  • 自定义注解和组件扫描在Spring Boot中动态注册Bean(二)
  • QEMU与KVM架构
  • 百度搜索引擎是如何解决用户点击率与网站排名关联度的呢?
  • 【ShuQiHere】K近邻算法(KNN)全面解析:从理论到实现
  • [Python]如何在Ubuntu中建置python venv虛擬環境,並安裝TensorFlow和OpenCV函式庫?
  • 1129.统计数字字符个数(vs2022中 gets, gets_s 无法使用的情况下)