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] 663. Equal Tree Partition 划分等价树的更多相关文章

  1. [LeetCode] 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】Symmetric Tree 推断一棵树是否是镜像的

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

  5. LeetCode 100. Same Tree (相同的树)

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  6. ✡ leetcode 156. Binary Tree Upside Down 旋转树 --------- java

    156. Binary Tree Upside Down Add to List QuestionEditorial Solution My Submissions   Total Accepted: ...

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

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

  8. Leetcode 101 Symmetric Tree 二叉树

    判断一棵树是否自对称 可以回忆我们做过的Leetcode 100 Same Tree 二叉树和Leetcode 226 Invert Binary Tree 二叉树 先可以将左子树进行Invert B ...

  9. LeetCode 107. Binary Tree Level Order Traversal II (二叉树阶层顺序遍历之二)

    Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...

随机推荐

  1. SpringBoot2版本Caused by: java.sql.SQLSyntaxErrorException: Table 'dinner.hibernate_sequenc

    1.SpringBoot2版本Caused by: java.sql.SQLSyntaxErrorException: Table 'dinner.hibernate_sequenc报错. -java ...

  2. 升级GCC

    1. wget http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.gz 2. tar -zxvf gcc-4.9.4.tar.gz 3. cd gc ...

  3. C#通过PInvoke调用c++函数的备忘录

    目前知道的情况被调用的C/C++函数只能是全局函数 不能调用类中的成员方法 被调用的C函数必须使用extern “C“包含,保证采用的导出函数名生成规则和.NET一致 函数调用约定通常使用WINAPI ...

  4. GAC 解释&路径

    GAC 全称是 Global Assembly Cache 作用是可以存放一些有很多程序都要用到的公共 Assembly ,例如 System.Data .System.Windows.Form 等等 ...

  5. Windows Service 服务搭配FluentScheduler实现定时任务调度

    Windows Service 服务 创建Windows Service 项目 创建一个Windows Service项目,并将项目名称改为 TaskWindowService 在解决方案资源管理器内 ...

  6. hashmap与hashtable的本质区别

    HashMap 底层数据结构是哈希表.线程不安全,效率高                哈希表依赖两个方法:hashCode()和equals()                执行顺序:       ...

  7. JMeter性能测试入门--简单使用

    1.JMeter整体简介 Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域. 它可以用于测试 ...

  8. MySQL整形手工注入

    0x1 判断注入点: http://www.xxx.org/members.php?id=1 and 1=1 --+ # ture http://www.xxx.org/members.php?id= ...

  9. BBR加速 Centos

    BBR是什么 BBR 是 Google 提出的一种新型拥塞控制算法,可以使 Linux 服务器显著地提高吞吐量和减少 TCP 连接的延迟. BBR项目地址 https://github.com/goo ...

  10. NBIOT实现UDP协议的发送和接收(包含软件升级)

    源码下载: nbiot_module程序(java netbean) -> 提取码 UdpServer程序(C# vs2010) -> 提取码 QQ:505645074 前提条件:开NB卡 ...