[Algo] 树型dp
1. 二叉搜索子树的最大键值和
// 1. 二叉搜索子树的最大键值和
// https://leetcode.cn/problems/maximum-sum-bst-in-binary-tree/
struct Info1 {
int maxSum;
int maxVal;
int minVal;
bool isBST;
int sum;
Info1(int a, int b, int c, bool d, int e) : maxSum(a), maxVal(b), minVal(c), isBST(d), sum(e) {}
};
Info1 func1(TreeNode* root) {
if (root == nullptr) return Info1(0, INT32_MIN, INT32_MAX, true, 0);
Info1 infol = func1(root->left);
Info1 infor = func1(root->right);
int maxVal = max(max(infol.maxVal, infor.maxVal), root->val);
int minVal = min(min(infol.minVal, infor.minVal), root->val);
bool isBST = infol.isBST & infor.isBST & infol.maxVal < root->val & root->val < infor.minVal;
int sum = infol.sum + infor.sum + root->val;
int maxSum = max(infol.maxSum, infor.maxSum);
if (isBST) maxSum = max(maxSum, sum);
return Info1(maxSum, maxVal, minVal, isBST, sum);
}
int maxSumBST(TreeNode* root) {
return func1(root).maxSum;
}
2. 在二叉树中分配硬币
// 2. 在二叉树中分配硬币
// https://leetcode.cn/problems/distribute-coins-in-binary-tree/description/
struct Info2 {
int move;
int cnt;
int sum;
Info2(int a, int b, int c) : move(a), cnt(b), sum(c) {}
};
Info2 func2(TreeNode* root) {
if (root == nullptr) return Info2(0, 0, 0);
Info2 infol = func2(root->left);
Info2 infor = func2(root->right);
int cnt = infol.cnt + infor.cnt + 1;
int sum = infol.sum + infor.sum + root->val;
int move = infol.move + infor.move + abs(infol.cnt - infol.sum) + abs(infor.cnt - infor.sum);
return Info2(move, cnt, sum);
}
int distributeCoins(TreeNode* root) {
return func2(root).move;
}
3. 监控二叉树
// 3. 监控二叉树
// https://leetcode.cn/problems/binary-tree-cameras/
int ans = 0;
// 递归含义
// 假设x上方一定有父亲的情况下,这个假设很重要
// x为头的整棵树,最终想都覆盖,
// 并且想使用最少的摄像头,x应该是什么样的状态
// 返回值含义
// 0: x是无覆盖的状态,x下方的节点都已经被覆盖
// 1: x是覆盖状态,x上没摄像头,x下方的节点都已经被覆盖
// 2: x是覆盖状态,x上有摄像头,x下方的节点都已经被覆盖
int func3(TreeNode* root) {
if (root == nullptr) return 1;
int retl = func3(root->left);
int retr = func3(root->right);
if (retl == 0 || retr == 0)
{
ans++;
return 2;
}
else if (retl == 1 && retr == 1) return 0;
else return 1;
}
int minCameraCover(TreeNode* root) {
if (func3(root) == 0) ans++;
return ans;
}
4. 路径总和 III
// 4. 路径总和 III
// https://leetcode.cn/problems/path-sum-iii/description/
int ans = 0;
void func4(TreeNode* root, int targetSum, long sum, unordered_map<long, int> &presum) {
if (root == nullptr) return;
sum += root->val;
ans += presum[sum - targetSum];
presum[sum]++;
func4(root->left, targetSum, sum, presum);
func4(root->right, targetSum, sum, presum);
presum[sum]--;
}
int pathSum(TreeNode* root, int targetSum) {
unordered_map<long, int> presum;
presum[0] = 1;
func4(root, targetSum, 0, presum);
return ans;
}