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. Android实用代码七段(三)

    正文  一.获取已经安装APK的路径 PackageManager pm = getPackageManager(); for (ApplicationInfo app : pm.getInstall ...

  2. C#编程语言之委托与事件(二)—— C#事件

    前面已经大致讲述了C#委托的一些基础知识点,本文接下来的内容是C#中的事件(Event),在此我提个建议,如果是刚接触C#的委托类型的朋友可以先看到这里,等熟悉了委托的使用之后(大约1-2天)再来了解 ...

  3. wps中如何插入参考文献

    最近学校论文规定要将参考文献在正文中引用,所以自己对这一方面做一下总结:点击插入尾注, 1:打开你的论文 2:点击"引用"--"插入尾注" 3:你会发现出现的不 ...

  4. 客户端(winform)更新

    winform更新有两种情况,一种是在线更新在线使用:直接右击项目发布出去就可以更新在线使用了.还有一种更新是不用一直连接网络的模式. 1:C#Winform程序如何发布并自动升级--------ht ...

  5. java 5并发中的阻塞队列ArrayBlockingQueue的使用以及案例实现

    演示一个阻塞队列的使用 public class BlockingQueueTest { public static void main(String[] args) { //创建一个包含三个元素的阻 ...

  6. JavaScript(第二十四天)【事件对象】

    JavaScript事件的一个重要方面是它们拥有一些相对一致的特点,可以给你的开发提供更多的强大功能.最方便和强大的就是事件对象,他们可以帮你处理鼠标事件和键盘敲击方面的情况,此外还可以修改一般事件的 ...

  7. hibernate框架学习错误集锦-org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL)

    最近学习ssh框架,总是出现这问题,后查证是没有开启事务. 如果采用注解方式,直接在业务层加@Transactional 并引入import org.springframework.transacti ...

  8. python实现京东秒杀

    # _*_coding:utf-8_*_ from selenium import webdriver import datetime import time driver = webdriver.C ...

  9. android 检查软件是否有更新版本

    import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import com.yuxin.m ...

  10. 标准C++类std::string的内存共享和Copy-On-Write(写时拷贝)

    标准C++类std::string的内存共享,值得体会: 详见大牛:https://www.douban.com/group/topic/19621165/ 顾名思义,内存共享,就是两个乃至更多的对象 ...