当前位置:网站首页>The 17th day of the special assault version of the sword offer
The 17th day of the special assault version of the sword offer
2022-08-02 09:21:00 【hys__handsome】
容易想到 O ( N 2 ) O(N^2) O(N2)brute force traversal algorithm,本质上跟forDouble-loop brute force traversal is similar,That is, the skills required to implement the code are more and more novel.
class Solution {
public:
//保证rootEach node in each of the following paths is picked,There will be no unselected nodes in the middle of the path
int dfs(TreeNode *root, int targetSum) {
if(!root) return 0;
int cnt = 0;
if(root->val == targetSum) cnt++;
cnt += dfs(root->left, targetSum - root->val);
cnt += dfs(root->right, targetSum - root->val);
return cnt;
}
int pathSum(TreeNode* root, int targetSum) {
if(!root) return 0;
//选取root点
int ans = dfs(root,targetSum);
//不选root点
ans += pathSum(root->left, targetSum);
ans += pathSum(root->right, targetSum);
return ans;
}
};
仔细思考会发现,There is a lot of double counting here,You can use prefix sums to optimize into O ( N ) O(N) O(N) 时间复杂度,where the prefix and value are placedmap的键上,The value is the number,This eliminates the need to re-traverse the previous prefix sum,Strictly speaking, because it is usedmapThis results in an algorithmic complexity of O ( N ∗ l o g N ) O(N*logN) O(N∗logN).
class Solution {
private:
unordered_map<long long, int> prefix;
// int ans = 0;
public:
int dfs(TreeNode *root, long long sum, int targetSum) {
if(!root) return 0;
sum += root->val;
int ans = 0;
if(prefix.count(sum-targetSum)) {
//sum - x = targetSum,其中xIt is a prefix sum in front of it
ans += prefix[sum-targetSum];
}
prefix[sum]++;
ans += dfs(root->left, sum, targetSum);
ans += dfs(root->right, sum, targetSum);
prefix[sum]--; //回溯,Otherwise, the sum of the nodes of other branches will be used
return ans;
}
int pathSum(TreeNode* root, int targetSum) {
prefix[0] = 1; //什么都没选,when arootThe sum of the starting path nodes is equal to targetSum时会用到
return dfs(root, 0, targetSum);
}
};
Use post-order traversal+DP思想
- Post-order traversal is to first find the maximum value of the left and right subpaths
- DPThe idea is that the current stack frame will calculate the current node+Left subpath+Right subpath(This cannot be backtracked to the parent node,Because the path is not linear),No matter what you want to backtrack to the parent node to the current node、当前+Left subpath、当前+Right subpath,The final result is the global maximum path sum.
class Solution {
private:
int res = INT_MIN;
public:
int maxPathSum(TreeNode* root) {
maxGain(root);
return res;
}
int maxGain(TreeNode *root) {
if(root == nullptr) return 0;
int left = maxGain(root->left);
int right = maxGain(root->right);
res = max(res, root->val); //Consider both the left and right paths to be negative
res = max(res, root->val + left);
res = max(res, root->val + right);
res = max(res, root->val + left + right);
//Backtracking can only return the current node value 或 当前+左 或 当前+右
return max(max(root->val,root->val+left), root->val+right);
}
};
代码简化版,It is better not to select when left and right are negative values,就为0
class Solution {
private:
int res = INT_MIN;
public:
int maxPathSum(TreeNode* root) {
maxGain(root);
return res;
}
int maxGain(TreeNode *root) {
if(root == nullptr) return 0;
//It is better not to select when left and right are negative values,就为0
int left = max(0,maxGain(root->left));
int right = max(0,maxGain(root->right));
res = max(res, root->val + left + right);
//Backtracking can only return the current node value 或 当前+左 或 当前+右
return max(left,right) + root->val;
}
};
最容易想到的方法,Save the in-order traversal sequence first,Then specify the right node of each node in sequence order,This is equivalent to creating a linked list
class Solution {
public:
void inorder(vector<TreeNode*> &ls, TreeNode *root) {
if(!root) return;
inorder(ls,root->left);
ls.emplace_back(root);
inorder(ls,root->right);
}
TreeNode* increasingBST(TreeNode* root) {
vector<TreeNode*> ls;
inorder(ls,root);
auto head = new TreeNode(-1);
auto tmp = head;
for(auto cur: ls) {
cur->left = cur->right = nullptr;
tmp->right = cur;
tmp = cur;
}
return head->right;
}
};
Come up with a harder way,Change the direction of the node pointer while traversing.Grab the inorder traversal algorithm->Traversal order invariant features.Then follow the traversal order with a move pointer.(有个坑,Move pointers cannot be placed in function parameters,A global variable is required,Because of the recursive backtracking process,Moving the pointer is still the same as it was and didn't change)
class Solution {
private:
TreeNode *cur = nullptr;
public:
void inorder(TreeNode *root) {
if(!root) return;
inorder(root->left);
root->left = nullptr;
cur->right = root;
cur = cur->right;
inorder(root->right);
}
TreeNode* increasingBST(TreeNode* root) {
auto head = new TreeNode(-1);
cur = head;
inorder(root);
return head->right;
}
};
边栏推荐
猜你喜欢

软件exe图标变记事本或浏览器、360压缩打不开的几种应急解决方法

百数应用中心——选择一款适合企业的标准应用

mysql连接池的实现

Jenkins--基础--6.2--Pipeline--语法--声明式

HCIP笔记十六天

Qt读取文件中内容(通过判断GBK UTF-8格式进行读取显示)

二维数组零碎知识梳理

Have you ever learned about these architecture designs and architecture knowledge systems?(Architecture book recommendation)

二分类和多分类

四字节的float比八字结的long范围大???
随机推荐
腾讯T8架构师,教你学中小研发团队架构实践PDF,高级架构师捷径
不用Swagger,那我用啥?
你有了解过这些架构设计,架构知识体系吗?(架构书籍推荐)
day_05 time 模块
干货|如何在海量文件系统中选择合适自己的文件系统
XML简介
【并发编程】- 线程池使用DiscardOldestPolicy策略、DiscardPolicy策略
“蔚来杯“2022牛客暑期多校训练营4
node封装一个图片拼接插件
SVN下载上传文件
使用scrapy 把爬到的数据保存到mysql 防止重复
What is the function of the import command of the page directive in JSP?
tf中tensor的大小输出
ABAP 和json转换的方法
Jenkins--基础--5.4--系统配置--全局工具配置
自定义卡包效果实现
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之一:解题思路
The use of thread pool and analysis of ThreadPoolExecutor source code
Openwrt_树莓派B+_Wifi中继
三国演义小说