1. 題目
給定一棵有 n 個結點的二叉樹,你的任務是檢查是否可以通過去掉樹上的一條邊將樹分成兩棵,且這兩棵樹結點之和相等。
樣例 1: 輸入: 5 / \ 10 10 / \ 2 3 輸出: True 解釋: 5 / 10 和: 15 10 / \ 2 3 和: 15 樣例 2: 輸入: 1 / \ 2 10 / \ 2 20 輸出: False 解釋: 無法通過移除一條樹邊將這棵樹划分成結點之和相等的兩棵子樹。 注釋 : 樹上結點的權值范圍 [-100000, 100000]。 1 <= n <= 10000
2. 解題
- 自底向上求得每個節點的子樹和,更新於節點的 val
- 遍歷檢查+剪枝,共計2次遍歷
- 實際上就是問這棵二叉樹是否存在一棵真子樹,其節點和等於總節點和的一半。可以兩遍DFS,第一遍算出整棵樹的節點和,第二遍查看是否有某棵子樹的節點和恰好等於整棵樹節點和的一半。代碼如下:、
public class Solution { private boolean res; private int sum; public boolean checkEqualTree(TreeNode root) { sum = dfs(root, root); if (sum % 2 != 0) { return false; } // 將答案初始化為false res = false; dfs(root, root); return res; } // 返回cur為根的子樹的節點和 private int dfs(TreeNode cur, TreeNode root) { if (cur == null) { return 0; } int left = dfs(cur.left, root), right = dfs(cur.right, root); if ((left + right + cur.val) * 2 == sum && cur != root) { res = true; } return left + right + cur.val; } } class TreeNode { int val; TreeNode left, right; public TreeNode(int val) { this.val = val; } }
方法二:
class Solution { Map<Integer, Integer> map = new HashMap<>(); public boolean checkEqualTree(TreeNode root) { if (root == null) return false; int total = getTotal(root); if (total%2 != 0) return false; if (total/2 == 0) return map.getOrDefault(total/2, 0) > 1; return map.containsKey(total/2); } private int getTotal(TreeNode root) { if (root == null) return 0; int total = root.val+getTotal(root.left)+getTotal(root.right); map.put(total, map.getOrDefault(total, 0)+1); return total; } }