Given a binary tree with n nodes, your task is to check if it's possible to partition the tree to two trees which have the equal sum of values after removing exactly one edge on the original tree.

Example 1:

Input:
5
/ \
10 10
/ \
2 3 Output: True
Explanation:
5
/
10 Sum: 15 10
/ \
2 3 Sum: 15

Example 2:

Input:
1
/ \
2 10
/ \
2 20 Output: False
Explanation: You can't split the tree into two trees with equal sum after removing exactly one edge on the tree.

Note:

  1. The range of tree node value is in the range of [-100000, 100000].
  2. 1 <= n <= 10000

这道题让我们划分等价树,就是说当移除一条边后,被分成的两棵树的结点之和需要相等。通过观察题目中的例子可以发现,如果将每个结点的结点值变成其所有子结点的结点值之和再加上当前的结点值,那么对于例子1来说,根结点的结点值就变成了 30,断开位置的结点就变成了 15,可以发现其实只要断开位置的结点值是根结点值的一半,就存在等价划分。所以这道题的难点就是更新每个结点的结点值,可以使用递归来做。博主最开始使用的是 unordered_set,把更新后的每个结点值都存入集合中,但是对于 test case: [0, 1, -1] 会 fail, 仔细分析下这个 case,发现更新后的根结点值还是0,而且0已经被存入集合了,而0除以2还是0,在集合中存在,会返回 true,但其实这棵树是不能等价划分的。0的情况确实比较特殊,所以这里要使用 HashMap,建立更新后的结点值和其出现次数之间的映射,这样只有 HashMap 中0的个数大于1的时候,才返回 true。这样完美的避开了根结点为0的陷阱,Perfect!参见代码如下:

解法一:

class Solution {
public:
bool checkEqualTree(TreeNode* root) {
unordered_map<int, int> m;
int sum = helper(root, m);
if (sum == ) return m[] > ;
return (sum % == ) && m.count(sum / );
}
int helper(TreeNode* node, unordered_map<int, int>& m) {
if (!node) return ;
int cur = node->val + helper(node->left, m) + helper(node->right, m);
++m[cur];
return cur;
}
};

我们也可以使用 stack 来做,将所有的结点和存入到栈中,然后依次出栈,看是否有结点和正好等于 sum/2,这里还是要注意当 sum=0 的情况同时根结点值又正好是0的情况,最简单的处理办法就是将栈顶元素提前移除,这样就不会有 sum=sum/2 这种情况发生了,参见代码如下:

解法二:

class Solution {
public:
bool checkEqualTree(TreeNode* root) {
stack<int> st;
int sum = helper(root, st);
st.pop();
if (sum % != ) return false;
while (!st.empty()) {
if (st.top() == sum / ) return true;
st.pop();
}
return false;
}
int helper(TreeNode* node, stack<int>& st) {
if (!node) return ;
st.push(helper(node->left, st) + helper(node->right, st) + node->val);
return st.top();
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/663

参考资料:

https://leetcode.com/problems/equal-tree-partition/

https://leetcode.com/problems/equal-tree-partition/discuss/149437/Logical-Thinking-with-Java-Code-Beats-97.25

https://leetcode.com/problems/equal-tree-partition/discuss/106727/JavaC%2B%2B-Simple-solution-with-only-one-HashMaplessgreater.

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Equal Tree Partition 划分等价树的更多相关文章

  1. [LeetCode] 663. Equal Tree Partition 划分等价树

    Given a binary tree with n nodes, your task is to check if it's possible to partition the tree to tw ...

  2. 663. Equal Tree Partition 能否把树均分为求和相等的两半

    [抄题]: Given a binary tree with n nodes, your task is to check if it's possible to partition the tree ...

  3. 【LeetCode】663. Equal Tree Partition 解题报告 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...

  4. LeetCode Same Tree (判断相同树)

    题意:如题 思路:递归解决,同判断对称树的原理差不多.先保证当前两个结点是相等的,再递归保证两左结点是相等的,再递归保证右结点是相等的. /** * Definition for a binary t ...

  5. LeetCode: Binary Tree Traversal

    LeetCode: Binary Tree Traversal 题目:树的先序和后序. 后序地址:https://oj.leetcode.com/problems/binary-tree-postor ...

  6. 【LeetCode】Symmetric Tree 推断一棵树是否是镜像的

    题目:Symmetric Tree <span style="font-size:18px;"><span style="font-size:18px; ...

  7. 【LeetCode】208. Implement Trie (Prefix Tree) 实现 Trie (前缀树)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:Leetcode, 力扣,Trie, 前缀树,字典树,20 ...

  8. [BZOJ3754]Tree之最小方差树

    3754: Tree之最小方差树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 402  Solved: 152[Submit][Status][Di ...

  9. 【LeetCode】86. Partition List 解题报告(Python)

    [LeetCode]86. Partition List 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http:// ...

随机推荐

  1. java排序算法(三):堆排序

    java排序算法(三)堆排序 堆积排序(HeapSort)是指利用堆积树这种结构所设计的排序算法,可以利用数组的特点快速定位指定索引的元素.堆排序是不稳定的排序方法.辅助空间为O(1).最坏时间复杂度 ...

  2. KVM之十:虚拟机在线添加网卡

    1.查看原有网卡信息 #virsh domiflist snale Interface Type Source Model MAC ---------------------------------- ...

  3. C#编程语言之委托与事件(一)—— C/C++函数指针和C#委托初步

    相信正在学习C#的人都有学习过C或C++的经验,本文要讲的第一个要点是C#中的委托(delegate,有些资料也叫代表).什么是委托,很多人都能自然而然地想到C/C++中的函数指针,事实上很多书和资料 ...

  4. beta冲刺1

    前言:这篇算是开始补之前的开端,毕竟beta阶段我们从前面开始就有在陆续做了. 今天的工作: 接收了新成员*1,然后几个人聚了一下,并且讨论了一下目前遇到的问题,以及目前需要处理的问题. 目前遇到的问 ...

  5. 201621123050 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识点组织起来.请使用工具画出本周学习到的知识点及知识点之间的联系.步骤如下: 1.1 写出你 ...

  6. 改变input的placeholder颜色

    input::-webkit-input-placeholder{ color:#666; } input::-ms-input-placeholder{ color:#666; } input::- ...

  7. JAVA_SE基础——45.基本类型变量.值交换[独家深入解析]

    需求:定义一个函数交换两个基本类型变量的值. 相信看过我前面的文章的同学都应该看的懂我以下的代码: class Demo2 { public static void main(String[] arg ...

  8. 进军ABP第一天:ABP理论知识

    1.2.3 领域层领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现. ( 实体(Entity ) 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表. ( 仓储(Repo ...

  9. 回收 PV - 每天5分钟玩转 Docker 容器技术(152)

    当 PV 不再需要时,可通过删除 PVC 回收. 当 PVC mypvc1 被删除后,我们发现 Kubernetes 启动了一个新 Pod recycler-for-mypv1,这个 Pod 的作用就 ...

  10. First:安装配置JDK and 部署Tomcat

    (一)准备 百度云地址(win,64Bit): 1.tomcat(7.0):链接:https://pan.baidu.com/s/1f60DOGO5Hnj9bq-987FNrw 密码:6q55 2.j ...