一、Problem
給定一個有 N 個結點的二叉樹的根結點 root,樹中的每個結點上都對應有 node.val 枚硬幣,並且總共有 N 枚硬幣。
在一次移動中,我們可以選擇兩個相鄰的結點,然後將一枚硬幣從其中一個結點移動到另一個結點。(移動可以是從父結點到子結點,或者從子結點移動到父結點。)。
返回使每個結點上只有一枚硬幣所需的移動次數。
輸入:[3,0,0]
輸出:2
解釋:從樹的根結點開始,我們將一枚硬幣移到它的左子結點上,一枚硬幣移到它的右子結點上。
輸入:[0,3,0]
輸出:3
解釋:從根結點的左子結點開始,我們將兩枚硬幣移到根結點上 [移動兩次]。然後,我們把一枚硬幣從根結點移到右子結點上。
提示:
1<= N <= 100
0 <= node.val <= N
二、Solution
方法一:後序遍歷
因爲我們要得到子節點的信息,所以後序遍歷最佳;又因爲最終的形狀是每個結點都只有 顆金幣,那假設某一個葉子結點 node 的金幣數爲 ,則結點分配一顆金幣所需要的步驟數爲(x-1), 的結果無外乎幾種:
- :表示該結點不需要分配金幣(已經有 1 顆金幣)
- :表示該結點沒有金幣,需要被分配
- :表示該結點的金幣數大於 ,此時也要將多餘的 顆硬幣移動
回到該葉子結點 node 的父親 fa,如果葉子結點需要的硬幣數爲 1,如果父親 fa 也沒有硬幣,那麼該父親 fa 向上傳遞的信息將會是 -2;但如果 fa 的右子節點有 2 個硬幣多餘,那麼 fa 向上傳遞的信息將會是 0
class Solution {
public:
int op;
int dfs(TreeNode* root) {
if (root == NULL)
return 0;
int l = dfs(root->left), r = dfs(root->right), cur = l+r+root->val;
op += abs(cur-1);
return cur-1;
}
int distributeCoins(TreeNode* root) {
dfs(root);
return op;
}
};
複雜度分析
- 時間複雜度:,
- 空間複雜度:,