超超超詳細題解:leetcode 979. Distribute Coins in Binary Tree

題目傳送門

題意

給出一棵二叉樹,樹的每個節點上都有指定數量的金幣。現在問,通過把金幣從相鄰節點間傳遞,每次只能移動一枚硬幣,最少需要移動多少次,能夠使得每個非空節點有且只有一枚硬幣

解法

我們定義函數dfs(x)表示節點x給父節點的金幣個數:正數代表子節點給父節點,負數代表子節點從父節點要過來金幣。那麼這個題就是求 全部非根結點需要移動次數的絕對值之和。即sum(abs(dfs(非根結點)))。下面用例子講解:
在這裏插入圖片描述
看上面這個例子,
dfs(左孩子)= -1:表示左孩子要從父節點那要過來1個。
dfs(右孩子)=-1:同理。
所以總移動次數=abs(dfs(左孩子))+abs(dfs(右孩子))=2。注意:我們要對孩子節點的dfs值取絕對值的。因爲送給父節點還是要過來都是要那麼多操作次數的
在這裏插入圖片描述
再看個例子,如上圖,dfs(左孩子)= 2,dfs(右孩子)=-1。總移動次數=dfs(左孩子)+abs(dfs(右孩子))=2+1=3。

所以這個題就是求 全部非根結點需要移動的次數的絕對值之和。爲啥是非根呢?因爲如果子節點都是1了,根結點肯定是1了嘛。

代碼實現在這裏插入圖片描述

我們還是看個例子:
如上圖,我們從下往上考慮每個小子樹。首先考慮左下角的那個0:

  1. 他沒有左子樹,那麼他的左子樹不需要移動硬幣。即dfs(l) = 0;
  2. 他的右子樹有三個節點,那麼需要移動兩次來達到1,因爲他自己需要留一個嘛。即dfs( r) = 2
  3. 那現在左下角這個0有2個硬幣了,他需要移動的硬幣數=左孩子給他的+右孩子給他的+他自己的-1。
  4. 其他以此類推。

注意這個dfs(x)並不是我們要的結果,我們要的結果是非節點的移動次數絕對值。所以上代碼。

python代碼

class Solution(object):
    def distributeCoins(self, root):
        self.ans = 0

        def dfs(node):
            if not node: return 0
            L, R = dfs(node.left), dfs(node.right)
            self.ans += abs(L) + abs(R)
            return node.val + L + R - 1

        dfs(root)
        return self.ans

java代碼

class Solution {
    int ans;
    public int distributeCoins(TreeNode root) {
        ans = 0;
        dfs(root);
        return ans;
    }

    public int dfs(TreeNode node) {
        if (node == null) return 0;
        int L = dfs(node.left);
        int R = dfs(node.right);
        ans += Math.abs(L) + Math.abs(R);
        return node.val + L + R - 1;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章