【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数

本文主要是介绍【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文涉及知识点

动态规划汇总
图论 深度游戏搜索 归并排序 组合

LeetCoce1569将子数组重新排序得到同一个二叉搜索树的方案数

给你一个数组 nums 表示 1 到 n 的一个排列。我们按照元素在 nums 中的顺序依次插入一个初始为空的二叉搜索树(BST)。请你统计将 nums 重新排序后,统计满足如下条件的方案数:重排后得到的二叉搜索树与 nums 原本数字顺序得到的二叉搜索树相同。
比方说,给你 nums = [2,1,3],我们得到一棵 2 为根,1 为左孩子,3 为右孩子的树。数组 [2,3,1] 也能得到相同的 BST,但 [3,2,1] 会得到一棵不同的 BST 。
请你返回重排 nums 后,与原数组 nums 得到相同二叉搜索树的方案数。
由于答案可能会很大,请将结果对 10^9 + 7 取余数。
示例 1:
输入:nums = [2,1,3]
输出:1
解释:我们将 nums 重排, [2,3,1] 能得到相同的 BST 。没有其他得到相同 BST 的方案了。
示例 2:
输入:nums = [3,4,5,1,2]
输出:5
解释:下面 5 个数组会得到相同的 BST:
[3,1,2,4,5]
[3,1,4,2,5]
[3,1,4,5,2]
[3,4,1,2,5]
[3,4,1,5,2]
示例 3:
输入:nums = [1,2,3]
输出:0
解释:没有别的排列顺序能得到相同的 BST 。
提示:
1 <= nums.length <= 1000
1 <= nums[i] <= nums.length
nums 中所有数 互不相同 。

归并排序

原以为必须用归并排序的思想,其实可以不用归并排序。

原理

对每棵树(子树),只讨论左子树和右子树之间的顺序,不讨论子树内部的顺序。
a,根节点必定是第一个。
b,混略内部顺序后,左子树的节点完全相同,假定其为ln个;右子树的节点也相同,假定其为rn个。就是组合 C m + n n \Large C_{m+n}^n Cm+nn
DFS 各子树 的结果相乘。

动态规划的状态表示

每个子树的范围是确定,比如:根节点的范围为[1,n],左子树[1,nums[0]-1] 右子树[nums[0],n]。每根子树,需要三个子状态:最小值(iMin),最大值(iMax),根节点的值(nums[iRoot])。 由于1到n,都出现且只出现一次,所以此子树的节点数为:最大值-最小值+1。

动态规划的转移方程

左树:iMin,nums[iRoot]-1, nums(iRoot…]中第一个在左树范围的小标。
右树:,nums[iRoot]+1,iMax,nums(iRoot…]中第一个在右树范围的小标。

动态规划的填表顺

深度优先,从根节点开始。

动态规划的返回值

dfs(1,n,0)-1。

代码

核心代码

template<int MOD = 1000000007>
class C1097Int
{
public:C1097Int(long long llData = 0) :m_iData(llData% MOD){}C1097Int  operator+(const C1097Int& o)const{return C1097Int(((long long)m_iData + o.m_iData) % MOD);}C1097Int& operator+=(const C1097Int& o){m_iData = ((long long)m_iData + o.m_iData) % MOD;return *this;}C1097Int& operator-=(const C1097Int& o){m_iData = (m_iData + MOD - o.m_iData) % MOD;return *this;}C1097Int  operator-(const C1097Int& o){return C1097Int((m_iData + MOD - o.m_iData) % MOD);}C1097Int  operator*(const C1097Int& o)const{return((long long)m_iData * o.m_iData) % MOD;}C1097Int& operator*=(const C1097Int& o){m_iData = ((long long)m_iData * o.m_iData) % MOD;return *this;}bool operator<(const C1097Int& o)const{return m_iData < o.m_iData;}C1097Int pow(long long n)const{C1097Int iRet = 1, iCur = *this;while (n){if (n & 1){iRet *= iCur;}iCur *= iCur;n >>= 1;}return iRet;}C1097Int PowNegative1()const{return pow(MOD - 2);}int ToInt()const{return m_iData;}
private:int m_iData = 0;;
};template<class Result = C1097Int<> >
class CCombination
{
public:CCombination(){m_v.assign(1, vector<Result>(1,1));}Result Get(int sel, int total){while (m_v.size() <= total){int iSize = m_v.size();m_v.emplace_back(iSize + 1, 1);for (int i = 1; i < iSize; i++){m_v[iSize][i] = m_v[iSize - 1][i] + m_v[iSize - 1][i - 1];}}return m_v[total][sel];}
protected:vector<vector<Result>> m_v;
};class Solution {
public:int numOfWays(vector<int>& nums) {m_nums = nums;return (DFS(1, nums.size(), 0) - 1).ToInt();}C1097Int<> DFS(int iMin, int iMax, int iRoot){int iLeftRoot = -1, iRightRoot = -1;for (int i = (int)m_nums.size()-1; i > iRoot; i--){if ((m_nums[i] < m_nums[iRoot])&&(m_nums[i] >= iMin )){iLeftRoot = i;}if ((m_nums[i] > m_nums[iRoot])&& (m_nums[i] <= iMax)){iRightRoot = i;}}C1097Int<> biRet = m_com.Get(m_nums[iRoot]-iMin,iMax-iMin);if (-1 != iLeftRoot){biRet *= DFS(iMin, m_nums[iRoot] - 1, iLeftRoot);}if (-1 != iRightRoot){biRet *= DFS(m_nums[iRoot] + 1,iMax, iRightRoot);}return biRet;}vector<int> m_nums;CCombination<> m_com;
};

2023年6月

class Solution {
public:
int numOfWays(vector& nums) {
m_vFact.emplace_back(1);
for (int i = 1; i < nums.size(); i++)
{
m_vFact.emplace_back(m_vFact.back()*i);
}
for (const auto& i : m_vFact )
{
m_vRevFact.emplace_back(i.PowNegative1());
}
return (Rev(nums) - 1).ToInt();
}
C1097Int<> Rev(vector& nums)
{
if (0 == nums.size())
{
return 1;
}
vector vLeft, vRight;
for (int i = 1; i < nums.size(); i++)
{
const int& n = nums[i];
if (n < nums[0])
{
vLeft.emplace_back(n);
}
else
{
vRight.emplace_back(n);
}
}
C1097Int<> iRet = m_vFact[vLeft.size() + vRight.size()] * m_vRevFact[vLeft.size()] * m_vRevFact[vRight.size()];
return iRet * Rev(vLeft) * Rev(vRight);
}
vector<C1097Int<>> m_vFact, m_vRevFact;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

这篇关于【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/654964

相关文章

redis中session会话共享的三种方案

《redis中session会话共享的三种方案》本文探讨了分布式系统中Session共享的三种解决方案,包括粘性会话、Session复制以及基于Redis的集中存储,具有一定的参考价值,感兴趣的可以了... 目录三种解决方案粘性会话(Sticky Sessions)Session复制Redis统一存储Spr

SpringBoot实现虚拟线程的方案

《SpringBoot实现虚拟线程的方案》Java19引入虚拟线程,本文就来介绍一下SpringBoot实现虚拟线程的方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录什么是虚拟线程虚拟线程和普通线程的区别SpringBoot使用虚拟线程配置@Async性能对比H

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

Python38个游戏开发库整理汇总

《Python38个游戏开发库整理汇总》文章介绍了多种Python游戏开发库,涵盖2D/3D游戏开发、多人游戏框架及视觉小说引擎,适合不同需求的开发者入门,强调跨平台支持与易用性,并鼓励读者交流反馈以... 目录PyGameCocos2dPySoyPyOgrepygletPanda3DBlenderFife

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

游戏闪退弹窗提示找不到storm.dll文件怎么办? Stormdll文件损坏修复技巧

《游戏闪退弹窗提示找不到storm.dll文件怎么办?Stormdll文件损坏修复技巧》DLL文件丢失或损坏会导致软件无法正常运行,例如我们在电脑上运行软件或游戏时会得到以下提示:storm.dll... 很多玩家在打开游戏时,突然弹出“找不到storm.dll文件”的提示框,随后游戏直接闪退,这通常是由于

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.