LeetCode刷题 | Day 5 分裂二叉树的最大乘积 (Maximum Product of Splitted Binary Tree) 递归深度优先算法
文章目录
前言
日常刷题,维持手感,同步学习英语,刷题顺序参考B站UP@justyyuk的系列视频,感兴趣的点波关注。
学海无涯,大路千万,感恩此程,彼此真诚陪伴!
Ps:第一次刷到的道友留步,这里拉齐一下信息。文章主要记录视频中的主要内容,算法思路会按照个人理解,用伪代码+举例每步输出的方式呈现(建议自己过一遍)。代码部分会以Python和C++语法进行呈现。文章最后会总结一些英语词汇。OK,就啰嗦这么多,开始进步[干杯🐱👓]
一、题目概述
输入:二叉树列表root
输出:该二叉树拆分之后两个子树的和的乘积的最大值
PS:
本题输出需要模10^9+7,原因有以下几点:
- 大质数: 10^9+7 是一个大质数,使用大质数作为模数可以减少哈希冲突,同时能保证取模运算的结果分布较为均匀。这在很多算法设计和竞赛中都是一个标准的选择。
- 避免溢出: 在涉及大整数乘法的情况下,结果很容易超过语言或平台的整数类型能表示的范围。通过取模操作,可以使得数字保持在一个较小的范围内,从而避免溢出问题。
- 性能优化: 现代计算机体系结构对于 2^k 这种数值的取模运算进行了优化(比如232−1或264−1 这种数)。虽然109+7不是2k,但其大小恰好适中,能在保证较好的数学性质的同时,依旧保持较好的计算效率。
- 通用性:10^9 + 7已成为许多算法竞赛和在线评测系统的默认模数。在这些环境中,使用这个模数使得你的算法具有通用性,并且容易被评测系统接受和比较结果。
- 避免冲突: 其他模数可能会导致一些特定情况下的冲突或不均匀分布,而10^9 + 7的大质数性质有助于减少这些问题。
二、解题方法
2.1 递归深度优先算法
2.1.1 思路讲解
策略描述:
- 采用深度优先搜索的方式构造一个集合sum,该集合中存放二叉树的所有子树的和;然后计算出原始二叉树所有节点值的和T;通过遍历集合sum,采用(T - i) * i的方式得到带求解的二叉树拆分之后两个子树的和的乘积的最大值。时间复杂度O(n),空间复杂度O(n)。
2.1.2 伪代码 + 逐步输出示例
# 伪代码示例
函数 maxProduct(root):
初始化一个空集合 sum
定义辅助函数 dfs(root)
如果 root 为空,返回 0
递归调用 dfs 计算左子树和右子树的和
将左子树和、右子树和及当前子树和(左子树和 + 右子树和 + root 的值)添加到 sum 集合
返回当前子树和
计算整棵树的总和 T = dfs(root)
初始化最大乘积 ans 为负无穷
遍历 sum 集合中的每一个子树和 i:
计算当前子树和与剩余部分和的乘积,并更新 ans 为最大值
返回 ans 对 10^9 + 7 取模的结果
# 逐步输出示例:
输入: [1, 2, 3]
初始化:
• 初始化集合sum
处理第一个元素 1:
• 递归处理左子树 2 和右子树 3
处理左子树 2:
• 左子树为空,返回 0
• 右子树为空,返回 0
• 当前子树和 = 0 + 0 + 2 = 2
• 更新 sum: {
0, 2}
处理右子树 3:
• 左子树为空,返回 0
• 右子树为空,返回 0