LeetCodee

823. Binary Trees with Factors

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

Given an array of unique integers arr, where each integer arr[i] 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 its children.

Return the number of binary trees we can make. The answer may be too large so return the answer modulo 10^9 + 7.

Examples:

Example 1:

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

Example 2:

Input: arr = [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]

Constraints:

  • 1 ≤ arr.length ≤ 1000
  • 2 ≤ arr[i] ≤ 10^9
  • All the values of arr are unique

Python Solution

class Solution:
    def numFactoredBinaryTrees(self, arr: List[int]) -> int:
        MOD = 10**9 + 7
        arr.sort()
        dp = {}
        
        for i, num in enumerate(arr):
            dp[num] = 1  # Tree with single node
            for j in range(i):
                if num % arr[j] == 0:  # arr[j] can be left child
                    right = num // arr[j]
                    if right in dp:  # If right child exists in array
                        dp[num] = (dp[num] + dp[arr[j]] * dp[right]) % MOD
                        
        return sum(dp.values()) % MOD

Implementation Notes:

  • Uses dynamic programming to build trees bottom-up
  • Sorts array to process smaller numbers first
  • Time complexity: O(n²)
  • Space complexity: O(n)

Java Solution

class Solution {
    public int numFactoredBinaryTrees(int[] arr) {
        int MOD = 1_000_000_007;
        Arrays.sort(arr);
        Map dp = new HashMap<>();
        
        for (int i = 0; i < arr.length; i++) {
            dp.put(arr[i], 1L);  // Tree with single node
            for (int j = 0; j < i; j++) {
                if (arr[i] % arr[j] == 0) {  // arr[j] can be left child
                    int right = arr[i] / arr[j];
                    if (dp.containsKey(right)) {  // If right child exists
                        long ways = dp.get(arr[j]) * dp.get(right) % MOD;
                        dp.put(arr[i], (dp.get(arr[i]) + ways) % MOD);
                    }
                }
            }
        }
        
        long sum = 0;
        for (long ways : dp.values()) {
            sum = (sum + ways) % MOD;
        }
        return (int) sum;
    }
}

C++ Solution

class Solution {
public:
    int numFactoredBinaryTrees(vector& arr) {
        const int MOD = 1e9 + 7;
        sort(arr.begin(), arr.end());
        unordered_map dp;
        
        for (int i = 0; i < arr.size(); i++) {
            dp[arr[i]] = 1;  // Tree with single node
            for (int j = 0; j < i; j++) {
                if (arr[i] % arr[j] == 0) {  // arr[j] can be left child
                    int right = arr[i] / arr[j];
                    if (dp.count(right)) {  // If right child exists
                        dp[arr[i]] = (dp[arr[i]] + dp[arr[j]] * dp[right]) % MOD;
                    }
                }
            }
        }
        
        long sum = 0;
        for (const auto& pair : dp) {
            sum = (sum + pair.second) % MOD;
        }
        return sum;
    }
};

JavaScript Solution

/**
 * @param {number[]} arr
 * @return {number}
 */
var numFactoredBinaryTrees = function(arr) {
    const MOD = 1e9 + 7;
    arr.sort((a, b) => a - b);
    const dp = new Map();
    
    for (let i = 0; i < arr.length; i++) {
        dp.set(arr[i], 1);  // Tree with single node
        for (let j = 0; j < i; j++) {
            if (arr[i] % arr[j] === 0) {  // arr[j] can be left child
                const right = arr[i] / arr[j];
                if (dp.has(right)) {  // If right child exists
                    const ways = (dp.get(arr[j]) * dp.get(right)) % MOD;
                    dp.set(arr[i], (dp.get(arr[i]) + ways) % MOD);
                }
            }
        }
    }
    
    let sum = 0;
    for (const ways of dp.values()) {
        sum = (sum + ways) % MOD;
    }
    return sum;
};

C# Solution

public class Solution {
    public int NumFactoredBinaryTrees(int[] arr) {
        const int MOD = 1_000_000_007;
        Array.Sort(arr);
        var dp = new Dictionary();
        
        for (int i = 0; i < arr.Length; i++) {
            dp[arr[i]] = 1;  // Tree with single node
            for (int j = 0; j < i; j++) {
                if (arr[i] % arr[j] == 0) {  // arr[j] can be left child
                    int right = arr[i] / arr[j];
                    if (dp.ContainsKey(right)) {  // If right child exists
                        long ways = dp[arr[j]] * dp[right] % MOD;
                        dp[arr[i]] = (dp[arr[i]] + ways) % MOD;
                    }
                }
            }
        }
        
        long sum = 0;
        foreach (var ways in dp.Values) {
            sum = (sum + ways) % MOD;
        }
        return (int)sum;
    }
}

Implementation Notes:

  • Uses Dictionary for dynamic programming
  • Handles modulo arithmetic for large numbers
  • Time complexity: O(n²)
  • Space complexity: O(n)