[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 题目讲解汇总(持续更新中...)

相关文章
相关标签/搜索