最大路径和,路径不必经过根节点
int maxPathSum(TreeNode* root) {
int ans = INT_MIN;
arrowSum(root, ans);
return ans;
}
// 返回从root往下的最大路径和
int arrowSum(TreeNode *root, int &ans) {
if (!root) return 0;
int left = arrowSum(root->left, ans);
int right = arrowSum(root->right, ans);
int arrow = root->val + max({0, left, right});
// 经过root的最大路径和
int pathSum = root->val + max(0, left) + max(0, right);
ans = max(ans, pathSum);
return arrow;
}
向下路径和为target的路径有多少条
平均O(nlgn),最坏O(n^2)
int pathSum(TreeNode* root, int sum) {
if (!root) return 0;
return searchFrom(root, sum)
+ pathSum(root->left, sum)
+ pathSum(root->right, sum);
}
int searchFrom(TreeNode *root, int sum) {
if (!root) return 0;
return (root->val == sum ? 1 : 0)
+ searchFrom(root->left, sum - root->val)
+ searchFrom(root->right, sum - root->val);
}
子段和的runningSum解法,O(n)
int pathSum(TreeNode *root, int target) {
unordered_map<int, int> presum = {{0,1}}; // sum=>count
int runningSum = 0;
int ans = 0;
search(root, target, runningSum, presum, ans);
return ans;
}
void search(TreeNode *root, int target, int runningSum,
unordered_map<int, int> &presum, int &ans) {
if (!root) return;
// 以当前节点结尾的子数组,希望能找到数组子段和runningSum-toFind=target
runningSum += root->val;
int toFind = runningSum - target;
if (presum.count(toFind)) ans += presum[toFind];
presum[runningSum]++;
search(root->left, target, runningSum, presum, ans);
search(root->right, target, runningSum, presum, ans);
presum[runningSum]--; // 回溯,为其他搜索路径准备
}