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

 

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

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

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.post

Example 1:url

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

Example 2:spa

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

Note:code

  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值都更新完成了,將其和算出來返回便可,參見代碼以下:htm

 

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;
    }
};

 

相似題目:blog

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 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索