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

news2024/11/26 7:41:18

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

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
    • 2. 理解问题和递推关系
      • 二叉搜索树的性质:
      • 核心思路:
      • 状态定义:
      • 状态转移方程:
      • 边界条件:
    • 3. 解决方法
      • 动态规划方法:
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释
  • C++代码
      • C++代码解释
  • 总结

题目描述

在这里插入图片描述

前言

不同的二叉搜索树问题 是一个经典的动态规划问题。给定一个整数 n,我们需要构造出由 n 个节点组成的所有不同的 二叉搜索树(BST)。在这类问题中,我们不仅需要理解二叉搜索树的性质,还需要通过动态规划来计算不同形态的二叉搜索树的数量。


基本思路

1. 问题定义

给定一个整数 n,求由 n 个节点构成的所有不同的二叉搜索树的数量。每个二叉搜索树的节点包含从 1n 的整数,每个整数只能使用一次。

2. 理解问题和递推关系

二叉搜索树的性质:

  • 二叉搜索树(BST)的性质是,对于每个节点:
    • 左子树上所有节点的值都小于该节点的值。
    • 右子树上所有节点的值都大于该节点的值。

核心思路:

如果我们选择节点 i 作为根节点,那么:

  1. 节点 1i-1 会组成根节点 i 的左子树。
  2. 节点 i+1n 会组成根节点 i 的右子树。
  3. 左子树和右子树的组合方式可以递归地进行计算,最终组合成完整的 BST。

状态定义:

dp[i] 表示 i 个节点能构成的不同二叉搜索树的数量。最终我们要求解的是 dp[n]

状态转移方程:

对于每一个根节点 i,它的左子树有 i-1 个节点,右子树有 n-i 个节点。左子树和右子树的组合方式相乘,即:
d p [ i ] = ∑ k = 1 i d p [ k − 1 ] × d p [ i − k ] dp[i] = \sum_{k=1}^{i} dp[k-1] \times dp[i-k] dp[i]=k=1idp[k1]×dp[ik]
其中,dp[k-1] 表示左子树的组合数,dp[i-k] 表示右子树的组合数。

边界条件:

  • n = 0 时,空树也是一种二叉搜索树,因此 dp[0] = 1

3. 解决方法

动态规划方法:

  1. 初始化一个数组 dp,其中 dp[0] = 1,表示空树。
  2. 使用递推公式计算 dp[i],即根据左子树和右子树的组合方式来更新 dp 数组。
  3. 最终 dp[n] 即为 n 个节点构成的不同二叉搜索树的数量。

伪代码:

initialize dp array with dp[0] = 1
for i from 1 to n:
    for j from 1 to i:
        dp[i] += dp[j-1] * dp[i-j]
return dp[n]

4. 进一步优化

  • 空间优化:由于每个 dp[i] 只依赖于之前的状态,因此我们已经使用最小的空间来存储这些状态。
  • 时间复杂度:动态规划的时间复杂度为 O(n^2),适合处理中等规模的输入。

5. 小总结

  • 问题思路:通过递归地构建左子树和右子树,利用动态规划的思想,可以高效计算不同二叉搜索树的数量。
  • 核心公式:状态转移方程 dp[i] = \sum_{k=1}^{i} dp[k-1] \times dp[i-k],每次通过左子树和右子树的组合方式进行计算。

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


Python代码

class Solution:
    def numTrees(self, n: int) -> int:
        # 初始化dp数组,dp[i]表示i个节点能构成的不同二叉搜索树的数量
        dp = [0] * (n + 1)
        dp[0] = 1  # 空树也是一种二叉搜索树
        
        # 动态规划计算每个dp[i]的值
        for i in range(1, n + 1):
            for j in range(1, i + 1):
                dp[i] += dp[j - 1] * dp[i - j]
        
        return dp[n]  # 返回n个节点能构成的不同二叉搜索树的数量

Python代码解释

  1. 初始化:定义一个 dp 数组,dp[i] 表示 i 个节点能构成的不同二叉搜索树的数量。初始值 dp[0] = 1,表示空树。
  2. 动态规划递推:使用状态转移公式更新 dp 数组,每次根据左子树和右子树的组合方式来累加。
  3. 返回结果:返回 dp[n],即 n 个节点可以构成的不同二叉搜索树的数量。

C++代码

class Solution {
public:
    int numTrees(int n) {
        // 初始化dp数组,dp[i]表示i个节点能构成的不同二叉搜索树的数量
        vector<int> dp(n + 1, 0);
        dp[0] = 1;  // 空树也是一种二叉搜索树

        // 动态规划计算每个dp[i]的值
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= i; ++j) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }

        return dp[n];  // 返回n个节点能构成的不同二叉搜索树的数量
    }
};

C++代码解释

  1. 初始化:定义一个 dp 数组,dp[i] 表示 i 个节点能构成的不同二叉搜索树的数量。初始值 dp[0] = 1,表示空树。
  2. 动态规划递推:使用状态转移公式更新 dp 数组,每次根据左子树和右子树的组合方式来累加。
  3. 返回结果:返回 dp[n],即 n 个节点可以构成的不同二叉搜索树的数量。

总结

  • 核心思路:通过递归构建不同的左子树和右子树,利用动态规划求解不同二叉搜索树的数量。每一个根节点的左子树和右子树的组合数相乘即为该根节点对应的不同二叉搜索树的数量。
  • 时间复杂度:时间复杂度为 O(n^2),适合处理中等规模的输入。
  • 动态规划应用:该问题展示了动态规划在树形结构问题中的应用,通过递推和组合的方式有效解决了求解二叉搜索树数量的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2210540.html

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

相关文章

计算机毕业设计 内蒙古旅游景点数据分析系统的设计与实现 Python毕业设计 Python毕业设计选题 Spark 大数据【附源码+安装调试】

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

FreeRTOS——剖析静态创建任务内部实现

静态创建任务函数 TaskHandle_t xTaskCreateStatic (TaskFunction_t pxTaskCode, /*指向任务函数的指针*/const char *const pcName, /*任务函数名*/const uint32_t ulStackDepth, /*任务堆栈大小注意字为单位*/void *const pvParameters, /*传递的任务函…

数据处理中常见的归一化方法有哪些?为什么要对数据进行归一化?

&#x1f381;&#x1f449;点击进入文心快码 Baidu Comate 官网&#xff0c;体验智能编码之旅&#xff0c;还有超多福利&#xff01;&#x1f381; &#x1f50d;【大厂面试真题】系列&#xff0c;带你攻克大厂面试真题&#xff0c;秒变offer收割机&#xff01; ❓今日问题&am…

Qt-系统QThread多线程介绍使用(62)

目录 描述 相关函数 使用 准备工作 重写run 发送信号 创建一个线程 启动线程 计时器运行流程 多线程运用场景 描述 qt多线程和Linux多线程类似 Linux有自己的一套多线程 API&#xff0c;Qt 也有着自己封装的多线程 API QT多线程参考了JAVA中的设计方式 QThread创建…

总结ES6—ES13新特性

目录 ES6let/const不同特性共同特性不能重复声明作用域提升问题暂时性死区&#xff08; temporal dead zone&#xff09;不添加window形成块级作用域 三者区别 模板字符串解构赋值数组的解构对象的解构 默认参数箭头函数展开运算符数值表示SymbolSetWeakSetMapWeakMapProxy 和 …

Linux Ubuntu dbus CAPI ---- #include<dbus.h>出现“无法打开源文件dbus/xxx.h“的问题

一、确保已安装dbus库和CAPI sudo apt-get install libdbus-1-dev 二、在c_cpp_properties.json的includePath中是否配置了dbus库依赖文件所在的路径 三、编译一个简单的dbus代码&#xff0c;在编译过程中只要出现.h文件找不到的情况&#xff0c;就使用下列命令找到.h文件路径…

【2024最新】基于springboot+vue的体质数据分析及可视化lw+ppt

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

【设计模式】揭秘Spring框架:设计模式如何驱动代码重用与扩展性的最佳实践

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 【设计模式】万字详解…

大数据毕业设计选题推荐-招聘信息数据分析系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

02.07.链表相交 最简方法之一

面试题 02.07. 链表相交 已解答 简单 相关标签 相关企业 提示 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链…

大家用 Flutter 做什么?Getx 遥遥领先!

大家用 Flutter 做什么&#xff1f;Getx 遥遥领先&#xff01; 视频 https://youtu.be/hXRgZwqdWzI https://www.bilibili.com/video/BV1VDHhedETz/ 前言 原文 大家用 Flutter 做什么&#xff1f; Reddit 上的一个关于 flutter 社区投票&#xff0c;询问大家用 flutter 做什…

STM32—W25Q64

1.W25Q64简介 W25Oxx系列是一种低成本、小型化、使用简单的非易失性存储器 易失性存储器 般就是SRAM、DRAM等非易失性存储器 般就是E2PROM、Flash等常应用于数据存储、字库存储、固件程序存储等场景存储介质&#xff1a;Nor Flash(闪存)时钟频率&#xff1a;80MHz / 160MHz(…

PyTorch中Tensor的存储结构

PyTorch中Tensor的存储结构 Tensor数据的类型 Tensor 中数据主要有下面两种类型&#xff1a; meta data&#xff1a;元数据&#xff0c;也就是描述数据特征的数据&#xff0c;例如 shape、dtype、device、stride等等raw data&#xff1a;数据本身&#xff0c;我们可以通过 t…

【漏洞复现】SpringBlade menu/list SQL注入漏洞

》》》产品描述《《《 致远互联智能协同是一个信息窗口与工作界面,进行所有信息的分类组合和聚合推送呈现。通过面向角色化、业务化、多终端的多维信息空间设计,为不同组织提供协同门户,打破组织内信息壁垒,构建统一协同沟通的平台。 》》》漏洞描述《《《 致远互联 FE协作办公…

【尚硅谷】FreeRTOS学笔记(更新中更新时间2024.10.12)

在网上看到的一段很形象的描述&#xff0c;放在这里给大家娱乐一下。 裸机开发&#xff1a;n个人拉屎&#xff0c;先进去一个拉完&#xff0c;下一个再来。看门狗&#xff1a;如果有人拉完屎还占着&#xff0c;茅坑刷视频&#xff0c;把他拖出去中断系统&#xff1a;n个人拉屎&…

Qt基础对话框QDialog

模态显示对话框 调用exec方法可以使得对话框模态显示&#xff0c;但是一个阻塞函数 [virtual slot] int QDialog::exec() 对话框的三个槽函数 accept [virtual slot] void QDialog::accept(); reject [virtual slot] void QDialog::reject() done [virtual slot] void QDia…

搭建mongodb单机部署-认证使用

搭建mongodb单机部署-认证使用 实现思路 先将配置文件配置好&#xff0c;使用不用认证的启动命令启动docker&#xff0c;然后创建账号并制定角色。在使用开启认证的命令重新启动容器就好。 这里我并没有说先停止容器&#xff0c;删掉容器重新创建容器。是因为我的启动命令中…

libaom 源码分析系列:noise_model.c 文件

libaom libaom 是 AOMedia(开放媒体联盟)开发的一个开源视频编解码器库,它是 AV1 视频压缩格式的参考实现,并被广泛用于多种生产系统中。libaom 支持多种功能,包括可扩展视频编码(SVC)、实时通信(RTC)优化等,并定期进行更新以提高压缩效率和编码速度 。 libaom 的一些…

豆包MarsCode体验有京东卡和现金

https://www.marscode.cn/events/s/iBpts1oT/ 先登录注册 然后到VSCODE里&#xff0c;在最左侧导航栏处看到EXTEBSIONS点一下&#xff08;快捷键CtrlShiftX&#xff09;&#xff0c;然后搜索MarsCode&#xff0c;并安装插件。 安装后登录体验一次问答即可。然后回到活动页即…

电瓶车的无钥匙启动功能为用户带来了极大的便利

电瓶车智能钥匙一键启动系统是一种依赖智能钥匙和一键启动按钮的启动方式。 智能钥匙和一键启动系统的结合使用提高了车辆的安全性&#xff0c;防止了未经授权的启动。 携带智能钥匙进入车辆&#xff0c;按下一键启动按钮&#xff0c;车辆通过感应智能钥匙存在而启动。 一键…