leetcode之二叉树类之路径和系列-----112/113/124/257/437 path sum(牵扯附加OJ572和OJ100, 子树和子拓扑)
来源:互联网 发布:淘宝温湿度控制板 编辑:程序博客网 时间:2024/06/06 02:42
OJ112:对路径定义为:从root到leaf的path,求路径和为target的路径是否存在
OJ113:对路径定义为:从root到leaf的path,求路径和为target的路径都有哪些
OJ437:对路径定义为:任意子树(含单节点)形成的路径,求路径和为target的路径有多少个
OJ124:对路径定义为:任意子树(含单节点)形成的路径,求路径和最大是多少
OJ257:对路径定义为:从root到leaf的path,求全部的路径
OJ112和OJ113和OJ257为一类,是单一递归可以解决的问题,并且都是需要做leaf才能够确认是否符合题目需求的情况,所以均用先序遍历;
OJ437和OJ124属于二叉树中的"子树类"问题,其中OJ437需要多层次递归来解决(注意OJ572也是"子树类"问题);
OJ112:只需要返回是否存在,首先路径已经被定义为从root到leaf,那么路径和必须在leaf才能做和target是否相同的判断,那么就做先序遍历,判断当前节点是否为leaf节点,非leaf的上层节点,返回左右子树的返回值的或;
OJ112代码:
class Solution {public: bool helper (TreeNode *cur, int sum) { if (cur) { if (!cur->left && !cur->right) { if (sum == cur->val) { return true; } else { return false; } } else { bool l = false, r = false; if (cur->left) { l = helper(cur->left, sum - cur->val); } if (cur->right) { r = helper(cur->right, sum - cur->val); } return l || r; } } } bool hasPathSum(TreeNode* root, int sum) { if (!root) { return false; } else if (!root->left && !root->right) { return (root->val == sum)?true:false; } return helper(root, sum); }};OJ113和OJ112唯一差别是,无需返回是否存在,仅需要在leaf节点确认路径和为target时,把这个路径记下来,代码稍作修改即可
OJ113代码:
class Solution {public: void helper (TreeNode *cur, int sum, vector<int> v, vector<vector<int>> &res) { if (cur) { v.push_back(cur->val); if (!cur->left && !cur->right) { if (sum == cur->val) { res.push_back(v); } } else { if (cur->left) { helper(cur->left, sum - cur->val, v, res); } if (cur->right) { helper(cur->right, sum - cur->val, v, res); } } } } vector<vector<int>> pathSum(TreeNode* root, int sum) { vector<vector<int>> res; if (!root) { return res; } vector<int> v; helper(root, sum, v, res); return res; }};
OJ257,打印从root到每一个leaf的全部路径,同样需要做leaf处才能够得到最终结果,这里的最终结果就是路径,所以和OJ112、OJ113一样也是先序遍历,当判断是leaf节点时,记录当前已走过的路径
OJ257代码:
class Solution {public: void helper (TreeNode *cur, string s, vector<string> &res) { if (cur) { if (!cur->left && !cur->right) { s += to_string(cur->val); res.push_back(s); } else { s += to_string(cur->val); s += "->"; helper(cur->left, s, res); helper(cur->right, s, res); } } } vector<string> binaryTreePaths(TreeNode* root) { vector<string> res; if (!root) { return res; } helper(root, "", res); return res; }};
OJ124:对路径定义为从一个任意点到另一个任意点的路径,求路径和最大的路径,而且没有路径值为正负零的约束
这种情况下在任何一个节点都有可能出现路径最大值,这时需要的是每个节点都要计算比较更新最大路径和。一般如果是到leaf节点才能见分晓做判断的都用先序遍历,每一个节点都需要做判断的用后序遍历,如本题。
核心思路点:
1、每一个节点处,都要做最大路径和的判断,判断来源包括:当前节点自己(cur->val)、当前节点左子节点到右子节点的路径和、当前节点到左子节点的路径和、当前节点到右子节点的路径和,取四者最大值和最大路径和max比较,如大于max则更像max;
2、每个节点要返回给上层节点当前层的"到本节点的最大路径和",也就是剔除掉当前节点左子节点到右子节点的路径和,因为当前节点是上层节点的左或右子节点,上层节点需要用本节点的最大路径和作为它的计算1的来源,这个是本题的核心,一定想清楚。即使用当前节点自己(cur->val)、当前节点到左子节点的路径和、当前节点到右子节点的路径和,取三者最大值,作为给上一层的返回值;除空节点返回0外,其他节点均返回计算结果给上一层;
最终结果就是不断更新得到的最大路径和max
OJ124代码:
class Solution {public: int helper (TreeNode *cur, int sum, int &max) { if (cur) { int left = helper(cur->left, sum + cur->val, max); int right = helper(cur->right, sum + cur->val, max); if (max < cur->val) { max = cur->val; } if (max < (cur->val + left)) { max = cur->val + left; } if (max < (cur->val + right)) { max = cur->val + right; } if (max < (cur->val + left + right)) { max = cur->val + left + right; } return std::max(cur->val, std::max(cur->val + left, cur->val + right)); } else { return 0; } } int maxPathSum(TreeNode* root) { if (!root) { return 0; } int max = INT_MIN; helper(root, 0, max); return max; }};
OJ437:路径被定义为任意一个节点到另一个任意节点,也可以是单节点构成一个路径,找出路径和为target的个数
典型的子树类问题,子树类问题典型的问题描述是:每一个"半截路径"即不是从root开始到leaf结尾的路径,而是任意节点A到任意节点B,A甚至可以和B是同一个节点;而具体对于本题的要求是:节点路径和为target的有多少个。
子树类问题的解决思维是:每一个节点都是root,每一个节点也都是leaf,
而更具体的解决框架是:当前节点、左子树、右子树同时发起递归,递归内部把输入的节点像根节点一样的处理
如root节点为A,左子节点为B右子节点为C,则同时发起A、B、C的递归,B、C进而发起它们各自的左右子节点的递归,即"每个节点都作为root"做处理;然后,递归处理函数中,也要做"每个节点都是leaf"的处理,对于本题就需要对每个路径(含单节点构成的路径)与target做比较,判断是否已经符合要求,同时还要判断加入每层节点后的路径是否又符合要求;
以一个极端例子,某子树节点为10,target就是10,该节点底下N多子节点,value都是0,那么它和全部子节点组成的各种路径都符合要求;
OJ437代码:
class Solution {public: int helper (TreeNode *cur, int c, const int sum) { if (cur) { c += cur->val; return (c == sum) + helper(cur->left, c, sum) + helper(cur->right, c, sum); } else { return 0; } } int pathSum(TreeNode* root, int sum) { int res = 0; if (!root) { return 0; } res = helper(root, 0, sum) + pathSum(root->left, sum) + pathSum(root->right, sum); return res; }};
牵扯到子树,看看另一个子树题,OJ572,判断一个二叉树A是否是另一个二叉树B的子树
注意:子树要求完全一致,不仅节点value和拓扑必须相同,而且不可有不同的子节点,如B的A部分,底下还有其他节点,那不行
先看下"两个树是否为相同的树"(OJ100),看如何做两个二叉树是否相同的判断方法
OJ100代码:
class Solution {public: bool helper (TreeNode *p, TreeNode *q) { if (!p && !q) { return true; } else if (!p || !q) { return false; } else { if (p->val == q->val) { bool l = helper(p->left, q->left); if (l) { return helper(p->right, q->right); } else { return false; } } else { return false; } } } bool isSameTree(TreeNode* p, TreeNode* q) { if (!p && !q) { return true; } else if (!p || !q) { return false; } return helper(p, q); }};
必须节点个数、拓扑、节点value完全相同才行,对于OJ572,如:
B是如下:
3 / \ 4 5 / \ 1 2 / 0A是如下:
4 / \ 1 2A不是B的子树;
但如果B是如下:
3 / \ 4 5 / \ 1 2A是如下:
4 / \ 1 2这样A就是B的子树;
所以OJ572是OJ100的扩展,OJ100是A和B是否相同,OJ572是A是否包含有B,子树类问题的典型解决方式:同时发起递归,递归处理函数内全部当作root一样处理
步骤:
1、当前节点、左子树、右子树同时发起递归处理;进而左、右子树下的每个节点都发起递归
2、递归处理函数和OJ100的完全一样
3、主函数只要发现符合要求的子树即返回true结束,没发现就一直递归处理下去
OJ572代码:
class Solution {public: bool helper (TreeNode *s, TreeNode *t) { if (!s && !t) { return true; } else if (!s || !t) { return false; } else { if (s->val == t->val) { return helper(s->left, t->left) && helper(s->right, t->right); } else { return false; } } } bool isSubtree(TreeNode* s, TreeNode* t) { if (!s && !t) { return true; } else if (!s || !t) { return false; } if (s->val == t->val) { if (helper(s, t)) { return true; } } return isSubtree(s->left, t) || isSubtree(s->right, t); }};
从这道题最重要需要掌握的是"子树类"问题的解决思维和解决模型;
另外,可以联想下,"比较A与B,或A与B的子树,不要拓扑完全相同,只要B也有A的结构,也就是说B的A部分还有其他子树也可以"这样的题怎么办,很显然,放宽了条件,不必一定是子树,也就不需要"!p && !q时返回true、!p || !q时返回false"的条件,取而代之的是需要比较A的左右和B的左右只要同时存在且value相同即可;所以,如果是A与B比较,那么形同OJ100的解决方法,如果是A与B的各种子树比较,就形同OJ572的解决方法。
- leetcode之二叉树类之路径和系列-----112/113/124/257/437 path sum(牵扯附加OJ572和OJ100, 子树和子拓扑)
- leetcode解题之112 & 113 & 437. Path Sum java版(二叉树路径和)
- Path Sum 二叉树路径和 @LeetCode
- LeetCode (12) Path Sum (二叉树路径和判断)
- 【leetcode 二叉树路径和】Path Sum 和 Path Sum II
- LeetCode OJ 之 二叉树最大子树和
- leetcode解题之124. Binary Tree Maximum Path Sum Java版 (二叉树的最大路径和)
- LeetCode OJ 之 Path Sum(求路径和)
- LeetCode OJ 之 Path Sum II (路径和 - 二)
- LeetCode OJ 之 Minimum Path Sum (最小路径和)
- leetcode之二叉树类之二叉树深度系列-----104/111/110/108/109 二叉树最大/最小深度/AVL树的判断和由有序序列生成(牵扯分治相关,OJ105/106)
- LeetCode Path Sum 路径和
- [LeetCode] 路径和 Path Sum
- leetcode Path Sum 路径和
- LeetCode-112-Path Sum(路径和)
- Leetcode 124 Binary Tree Maximum Path Sum 二叉树最大路径和
- 437. Path Sum III(二叉树的路径和之三)
- [LeetCode]437. Path Sum III(求二叉树中路径和等于sum的数量)
- MYSQL数据库
- 2017/10/14周测(vjudge——BJFU周赛_6th_1st)
- UML类间的关系
- 欢迎使用CSDN-markdown编辑器
- 10月14号总结
- leetcode之二叉树类之路径和系列-----112/113/124/257/437 path sum(牵扯附加OJ572和OJ100, 子树和子拓扑)
- python学习:序列
- c#调用win32 API函数修改系统时间
- 【Leetcode-easy-617】Merge Two Binary Trees
- win10 + VS2013 + Qt5.6.0安装与环境配置
- 新手必学的matlab常用
- Incremental Learning of Object Detectors without Catastrophic Forgetting 论文阅读
- Linux内核很吊之 module_init解析 (下)
- XML三种解析方式简介以及JAVA实现