[LeetCode] Binary Trees With Factors 帶因子的二叉樹


 

Given an array of unique integers, each integer is strictly greater than 1.

We make a binary tree using these integers and each number may be used for any number of times.

Each non-leaf node's value should be equal to the product of the values of it's children.

How many binary trees can we make?  Return the answer modulo 10 ** 9 + 7.

Example 1:

Input: A = [2, 4]
Output: 3
Explanation: We can make these trees: [2], [4], [4, 2, 2]

Example 2:

Input: A = [2, 4, 5, 10]
Output: 7
Explanation: We can make these trees: [2], [4], [5], [10], [4, 2, 2], [10, 2, 5], [10, 5, 2].

Note:

  1. 1 <= A.length <= 1000.
  2. 2 <= A[i] <= 10 ^ 9.
 

這道題給了我們一些不相同的數字,每個都大於1,數字可以重復使用且可以部分使用,問我們可以建立多少棵二叉樹使得每個非葉結點的值等於其左右子結點值的乘積。並提示了結果可能會很大,讓我們把結果對一個超大數取余。看到這里,刷題老司機們應該瞬間反應過來了吧,應該是用動態規划Dynamic Programming來做,為啥呢,不可能去遞歸遍歷所有的情況阿,這么大的數,機子都要爆了。好吧,既然選定了DP,兩個難點,定義dp表達式跟推導狀態轉移方程。怎么簡單怎么來唄,我們用一個一維dp數組,其中dp[i]表示值為i的結點做根結點時,能夠形成的符合題意的二叉樹的個數。這樣我們將數組A中每個結點的dp值都累加起來就是最終的結果了。好了,有了定義式,接下來就是最大的難點了,推導狀態轉移方程。題目中的要求是根結點的值必須是左右子結點值的乘積,那么根結點的dp值一定是跟左右子結點的dp值有關的,是要加上左右子結點的dp值的乘積的,為啥是乘呢,比如有兩個球,一個有2種顏色,另一個有3種顏色,問兩個球放一起總共能有多少種不同的顏色組合,當然是相乘啦。每個結點的dp值初始化為1,因為就算是當個光桿司令的葉結點,也是符合題意的,所以至少是1。然后就要找其左右兩個子結點了,怎么找,有點像 Two Sum 的感覺,先確定一個,然后在HashMap中快速定位另一個,想到了這一層的話,我們的dp定義式就需要做個小修改,之前說的是用一個一維dp數組,現在看來就不太合適了,因為我們需要快速查找某個值,所以這里我們用一個HashMap來定義dp。好,繼續,既然要先確定一個結點,由於都是大於1的正數,那么這個結點肯定要比根結點值小,為了遍歷方便,我們想把小的放前面,那么我們就需要給數組A排個序,這樣就可以遍歷之前較小的數字了,那么如何快速定位另一個子結點呢,我們只要用根結點值對遍歷值取余,若為0,說明可以整除,然后再在HashMap中查找這個商是否存在,在的話,說明存在這樣的兩個結點,其結點值之積等於結點A[i],然后我們將這兩個結點值之積加到dp[A[i]]中即可,注意還要對超大數取余,防止溢出。最后當所有結點的dp值都更新完成了,將其和算出來返回即可,參見代碼如下:

 

class Solution {
public:
    int numFactoredBinaryTrees(vector<int>& A) {
        long res = 0, M = 1e9 + 7;
        unordered_map<int, long> dp;
        sort(A.begin(), A.end());
        for (int i = 0; i < A.size(); ++i) {
            dp[A[i]] = 1;
            for (int j = 0; j < i; ++j) {
                if (A[i] % A[j] == 0 && dp.count(A[i] / A[j])) {
                    dp[A[i]] = (dp[A[i]] + dp[A[j]] * dp[A[i] / A[j]]) % M;
                }
            }
        }
        for (auto a : dp) res = (res + a.second) % M;
        return res;
    }
};

 

類似題目:

Two Sum

 

參考資料:

https://leetcode.com/problems/binary-trees-with-factors/

https://leetcode.com/problems/binary-trees-with-factors/discuss/125794/C%2B%2BJavaPython-DP-solution

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM