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

news2024/12/25 18:18:10

动态规划—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 = left
                root.right = right
                all_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 = left
                        root.right = right
                        all_trees.append(root)
            
            return all_trees
        
        return 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.coloradmin.cn/o/2210064.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux高级编程_32_磁盘映射

文章目录 磁盘映射相关函数mmap函数作用&#xff1a; munmap函数作用&#xff1a; truncate 函数作用&#xff1a; 语法&#xff1a;使用步骤&#xff1a; 磁盘映射 概述&#xff1a; > 存储映射 I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。…

Excel中Ctrl+e的用法

重点&#xff1a;想要使用ctrle&#xff0c;前提是整合或拆分后的结果放置的单元格必须和被提取信息的单元格相邻&#xff0c;且被提取信息的单元格也必须相连。 下图为错误示例 这样则可以使用ctrle 1、信息整合 2、提取信息 3、添加符号 4、信息顺序调换 5、数字提取 crtle还…

AI测试之 TestGPT

如今最火热的技术莫非OpenAI的ChatGPT莫属&#xff0c;AI技术也在很多方面得到广泛应用。今天我们要介绍的TestGPT就是一个软件测试领域中当红的应用。 TestGPT是什么&#xff1f; TestGPT是一家总部位于以色列特拉维夫的初创公司 CodiumAI Ltd.&#xff0c;发布的一款用于测…

Android:记录一个打包发布版的release包以后闪退的问题

个人感觉其实release闪退的问题挺难排查的&#xff0c;因为release包运行起来as捕获不到相应的应用程序进程&#xff0c;从而不易查看到日志&#xff0c;也是我玩得不溜&#xff0c;大家有不同的方法可以评论区探讨&#xff0c;我也定期回复一些评论一起讨论。以下是我遇到的情…

高效的读书与笔记管理:打造个人知识体系

01 读书学习的常见问题 1、读书⼯具分散&#xff0c;划线和笔记分散&#xff0c;导致我们的复习、搜索效率低。⽐如不同书籍中&#xff0c;提到了同⼀个问题的观点&#xff0c;很难进行关联。 2、读书&#xff0c;仅限于读&#xff0c;知道别⼈的观点&#xff0c;但是缺乏内…

【AI论文精读13】RAG论文综述2(微软亚研院 2409)P5-可解释推理查询L3

AI知识点总结&#xff1a;【AI知识点】 AI论文精读、项目、思考&#xff1a;【AI修炼之路】 P1&#xff0c;P2&#xff0c;P3&#xff0c;P4 五、可解释推理查询&#xff08;L3&#xff09; ps&#xff1a;P2有四种查询&#xff08;L1&#xff0c;L2&#xff0c;L3&#xff0c;…

学习记录:js算法(六十二):单词搜索 II

文章目录 单词搜索 II思路一思路二 单词搜索 II 给定一个 m x n 二维字符网格 board 和一个单词&#xff08;字符串&#xff09;列表 words&#xff0c; 返回所有二维网格上的单词 。 单词必须按照字母顺序&#xff0c;通过 相邻的单元格 内的字母构成&#xff0c;其中“相邻”…

crashrpt3 开源项目的Vs 2022 C++20及其以上的编译

1. 首先从github 下载源代码 crashrpt3 2. 用CMake Gui 编译成vs studio 工程文件 2.1 点击 config 按钮 2.2 依次点击 Generate 按钮、Open Project 按钮.之后vs 2022 会打开编译好的sln工程文件 3.全选解决方案里面的所有项目,设置C语言标准,我这里设置是最新C,即启用的是…

Solidity基础语法

Solidity的在线编辑器&#xff1a;https://remix.ethereum.org/ 一、合约结构 1、SPDX许可标识&#xff1a;指定代码的开源许可 2、pragma指令&#xff1a;声明Solidity版本 3、导入语句&#xff1a;引入其他合约或库 4、合约声明&#xff1a;使用contract关键字 5、状态变量&…

【关系模型】关系完整性约束

按照上面的框架我们已经讲了关系数据结构还有关系操作&#xff0c;今天来补充这一章的关系完整性约束 关系完整性约束 完整性约束 完整性约束可以保证数据的一致性和元组的唯一性 实体完整性约束 比如在学生表中&#xff0c;每一个元组都应该是唯一并且元组之间是可以区分…

JavaScript(Web APIs 作用和分类,DOM数是什么,document是什么,根据css选择器来获取DOM元素,修改DOM元素的方式,边量声明)

变量声明 变量声明有三个 var let 和 const建议&#xff1a; const 优先&#xff0c;尽量使用const&#xff0c;原因是&#xff1a; const 语义化更好 很多变量我们声明的时候就知道他不会被更改了&#xff0c;那为什么不用 const呢&#xff1f; 实际开发中也是&#xff0c;…

【unity框架开发8】unity场景Scene的使用, 如何封装一个场景管理器

文章目录 一、场景基本操作1、加载切换场景2、获取场景信息3、激活场景4、场景基本属性获取5、已加载场景个数6、获取场景中所有物体7、创建新场景8、卸载销毁场景 二、使用协程方法来异步加载场景1、AsyncOperation相关的代码应写在一个协同程序中。2、allowSceneActivation加…

AI深湖DeepLate人工智能的数据集格式开源项目

人工智能的数据集格式 文档 • 入门 • API 参考 • 例子 • 博客 • Slack 社区 • Twitter&#xff08;推特&#xff09; 用其他语言阅读这篇文章: English 深湖 Deep Lake Deep Lake 是一种数据集格式&#xff0c;提供简单的 API 以用于创建、存储和协作处理任何规模的…

Spring Security 与 OAuth 2.0 登录实现指南

文章目录 一、项目概述二、环境准备三、创建GitHub OAuth应用四、项目依赖配置五、配置OAuth 2.0六、创建控制器七、创建视图八、运行应用九、用户界面展示十、总结 在现代的Web应用中&#xff0c;安全性是一个不可忽视的因素。OAuth 2.0作为一种流行的授权框架&#xff0c;提供…

浅析主流监控告警系统基本架构和原理

浅析主流监控告警系统基本架构和原理 一&#xff0c;监控系统的作用和目前主流监控系统 1&#xff0c;作用&#xff1a;监控系统一般有以下这几个作用 实时采集监控数据&#xff1a;包括硬件、操作系统、中间件、应用程序等各个维度的数据。实时反馈监控状态&#xff1a;通过…

论文笔记:RelationPrompt :Zero-Shot Relation Triplet Extraction

论文来源: ACL Findings 2022 论文链接:https://arxiv.org/pdf/2203.09101.pdf 论文代码:http://github.com/declare-lab/RelationPrompt 本篇论文是由阿里达摩院自然语言智能实验室于2022年发表的关于零样本关系抽取的顶会论文,本篇博客将记录我在阅读过程中的一些笔记…

AI自动生成PPT解决方案,AI生成PPT-PrensentationGen-Java实现

AI自动生成PPT解决方案&#xff0c;AI生成PPT-PrensentationGen-Java实现。 利用大语言模型生成PPT文件的SpringBoot Web应用&#xff0c;主要功能是自动化创建演示文稿&#xff0c;适用于快速制作演示材料&#xff0c;特色在于其高效的模板处理和文本替换技术。 点击视频观看…

Python入门:如何在Python中优雅地书写多行字符串!

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 多行字符串📒📝 什么是多行字符串?📝 三重引号📝 字符串连接📝 反斜杠⚓️ 相关链接 ⚓️📖 介绍 📖 在编程过程中,时常会遇到需要使用多行字符串的场景。例如,在编写长参数、描述文本或代码文档时,多行字符串…

java生成日历数据列表并按日历格式导出到excel

日历格式输出 日历数据列表导出封装日历格式实体类效果 日历数据列表 /**** 封装日历数据* param year 年份* param month 月份*/public List<InspectionDailyStaffPlanCalendarData> selectCalendarDataList(int year,int month,List<InspectionDailyStaffPlan> …

centos7 Oracle 11g rac 静默安装(NFS配置共享存储)

1.环境信息准备 注意&#xff1a; 在配置网络时&#xff0c;Oracle RAC的每个节点必须具有至少两个以上的网卡&#xff0c;一张网卡对外提供网络服务&#xff0c;另一张网卡用于各个节点间的通信和心跳检测等。在配置RAC集群的网卡时&#xff0c;如果节点1的公共接口是eth0&…