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

【C++动态规划 排序】823. 带因子的二叉树|1899

本文涉及知识点

C++动态规划 排序

LeetCode823. 带因子的二叉树

给出一个含有不重复整数元素的数组 arr ,每个整数 arr[i] 均大于 1。
用这些整数来构建二叉树,每个整数可以使用任意次数。其中:每个非叶结点的值应等于它的两个子结点的值的乘积。
满足条件的二叉树一共有多少个?答案可能很大,返回 对 109 + 7 取余 的结果。
示例 1:
输入: arr = [2, 4]
输出: 3
解释: 可以得到这些二叉树: [2], [4], [4, 2, 2]
示例 2:
输入: arr = [2, 4, 5, 10]
输出: 7
解释: 可以得到这些二叉树: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2].
提示:
1 <= arr.length <= 1000
2 <= arr[i] <= 109
arr 中的所有值 互不相同

动态规划 排序

所有节点的值>1,父亲节点值=两个子节点的值的积。 → \rightarrow 父节点的值 > 子节点的值。
nums升序排序,mIndex记录nums[i] To i。
next[i] 记录所有符合条件的{j,k} nums[i] = nums[j]*nums[k]

动态规划的状态表示

dp[i]表示以值的编号为i为根的二叉树数量。

动态规划的填表顺序

i从0到N-1处理,这样可以保子树已经处理完。

动态规划的转移方程

dp[i]=1
for([j,k] : next[i])
dp[i] += dp[j]*dp[k];

动态规划初始值

dp全为0

动态规划的返回值

dp之和。

代码

核心代码

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;
	}
	C1097Int  operator/(const C1097Int& o)const
	{
		return *this * o.PowNegative1();
	}
	C1097Int& operator/=(const C1097Int& o)
	{
		*this /= o.PowNegative1();
		return *this;
	}
	bool operator==(const C1097Int& o)const
	{
		return m_iData == o.m_iData;
	}
	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;;
};

class Solution {
		public:
			int numFactoredBinaryTrees(vector<int>& arr) {
				const int N = arr.size();
				sort(arr.begin(), arr.end());	
				unordered_map<int, int> mIndex;
				for (int i = 0; i < arr.size(); i++) {
					mIndex[arr[i]] = i;
				}
				vector<vector<pair<int, int>>> next(N);
				for (int i = 0; i < N; i++) {
					for (int j = 0; j < N; j++) {
						long long tmp = (long long)arr[i] * arr[j];
						if ((tmp <= INT_MAX) && mIndex.count(tmp)) {
							next[mIndex[tmp]].emplace_back(i, j);
						}
					}
				}
				vector<C1097Int<>> dp(N);
				for (int i = 0; i < N; i++) {
					dp[i] = 1;
					for (auto [j, k] : next[i]) {
						dp[i] += dp[j] * dp[k];
					}
				}
				auto ans = accumulate(dp.begin(), dp.end(), C1097Int<>());
				return ans.ToInt();
			}
		};

单元测试

vector<int> arr;	
		TEST_METHOD(TestMethod1)
		{
			arr = { 2, 4 };
			auto res = Solution().numFactoredBinaryTrees(arr);
			AssertEx(3, res);
		}
		TEST_METHOD(TestMethod2)
		{
			arr = { 2, 4, 5, 10 };
			auto res = Solution().numFactoredBinaryTrees(arr);
			AssertEx(7, res);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

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


http://www.kler.cn/a/519157.html

相关文章:

  • chrome插件:网站视频下载
  • HashTable, HashMap, ConcurrentHashMap 之间的区别
  • 深入了解 HTTP 头部中的 Accept-Encoding:gzip、deflate、br、zstd
  • 【深入理解SpringCloud微服务】Sentinel规则持久化实战
  • 代码随想录算法训练营day31(补0124)
  • docker搭建redis集群(三主三从)
  • vue中使用jquery 实现table 拖动改变尺寸
  • linux 管道符、重定向与环境变量
  • 软件质量与测试报告5-压力测试 JMeter 与 Badboy
  • C语言进阶——3字符函数和字符串函数(2)
  • 即梦(Dreamina)技术浅析(二):后端AI服务
  • 蓝桥杯算法赛第25场月赛
  • Flutter:搜索页,搜索bar封装
  • mysql_use_result的概念和使用案例
  • OpenCV:二值化与自适应阈值
  • Chameleon(变色龙) 跨平台编译C文件,并一次性生成多个平台的可执行文件
  • JavaScript系列(43)--依赖注入系统实现详解
  • [极客大挑战 2019]BuyFlag1
  • vue高级组件封装 element组件二次封装
  • Maui学习笔记- SQLite简单使用案例