前往
大廳
主題

LeetCode - 2440. Create Components With Same Value 解題心得

Not In My Back Yard | 2023-09-04 12:00:01 | 巴幣 0 | 人氣 77

題目連結:


題目意譯:
現在存在著一個有著 n 個節點無向樹,節點編號為 0 到 n - 1。

你被給定一個索引值從 0 開始且長度為 n 的整數陣列 nums,其中 nums[i] 代表第 i 個節點的數值。你同時也被給定一個二維且長度 n - 1 的整數陣列 edges,其中 edges[i] = [ai, bi] 代表著在樹中節點 ai 和節點 bi 之間有一條邊。

你被允許刪掉其中一些邊,將該樹分拆成若干個連通元件(Connected Components)。令一個元件的數值為 nums[i] 之總和,其中節點 i 位於該元件之中。

回傳你最多可以刪除的邊數,使得樹中每個連通元件之數值相同。

限制:
1 ≦ n ≦ 2 × 10 ^ 4
nums.length == n
1 ≦ nums[i] ≦ 50
edges.length == n - 1
edges[i].length == 2
0 ≦ edges[i][0], edges[i][1] ≦ n - 1
edges 代表著一個合法的樹。



範例測資:
範例 1:
輸入: nums = [6,2,2,2,6], edges = [[0,1],[1,2],[1,3],[3,4]]
輸出: 2
解釋: 上圖顯示著我們可以刪除 [0,1] 和 [3,4] 這些邊。因此而得的連通元件依序為 [0] 、 [1,2,3] 和 [4]。每一個元件的數值皆等於 6。可以證明沒有更好的刪除方式存在,所以答案為 2。

範例 2:
輸入: nums = [2], edges = []
輸出: 0
解釋: 沒有可以刪除的邊存在。


解題思維:
首先從輸入給定的 edges 建立出圖的鄰接表(Adjacency List,如這題)。

可以看到每個元件的總和都一樣的話,則代表著該總和值為原本的樹全部節點值之總和(令此全節點值總和為 T)的一個因數。

因此我們可以掃過 T 的每一個因數,而實際上我們不需要掃過 1 ~ T 的所有整數,只要掃過 1 ~ sqrt(T) 即可知道 T 有哪些因數。其中 sqrt(x) 代表為 x 的平方根。

所以如果我們知道可以把原本的樹分拆成若干個各自總和為 Q 的元件,其中 Q 為 T 的一個因數。則可以看到元件總數為 T ÷ Q。而因為我們的圖是一棵「樹」,因此每刪掉一條邊便會把一個元件一分為二。因此對於 Q 來說,我們需要刪掉 T ÷ Q - 1 條邊形成這些元件。



那要怎麼檢查一個因數 Q 可不可行呢?只要把隨便一個點當作這棵無向且無根的樹之根節點(在這邊,以節點 0 作為根節點)。則我們只要從這邊遞迴求解即可:
    當我們位於節點 i 時,我們可以先遞迴其所有子樹。而每個子樹的回傳值是各自試圖分完總和值恰好為 Q 的元件後剩下的節點總和值(注意:其值不一定小於 Q)。

    接著把每一個子樹的剩餘的數值(回傳值)再加上節點 i 的數值加總後,判斷一下該總和值是否恰好為 Q。如果是則將目前整體已分出來的元件數,並回傳 0(因為剛好沒有剩餘的數值);反之,則直接回傳該總和值(即便總和值 > Q),因為這些節點目前無法形成一個元件。

最後所有節點的結果都求完之後,最後檢查總計形成的元件數是否恰好為 T ÷ Q 個。如果不是則代表 Q 是不可行的。

而當中所有可行的 Q 值中,越小者越好,因為可以形成更多的元件。而元件數最大值減去 1 之後,即是我們所求的最多可刪除邊數。




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作