[LeetCode] 823. Binary Trees With Factors

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 109 + 7.

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] <= 109
  • All the values of arr are unique.

带因子的二叉树。

给出一个含有不重复整数元素的数组,每个整数均大于 1。

我们用这些整数来构建二叉树,每个整数可以使用任意次数。

其中:每个非叶结点的值应等于它的两个子结点的值的乘积。

满足条件的二叉树一共有多少个?返回的结果应模除 10 ** 9 + 7。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-trees-with-factors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题虽然说的是构建树,但是其实是一道数学题,我参考了这个帖子。思路是 hashmap + sort。既然树的构建需要满足 node.val = node.left.val * node.right.val,那么先把 input 排序,这样在找孩子节点的时候会方便很多。排序过后,比如我们从 1 遍历到 nums[i] 了,此时如果把 nums[i] 当做父节点,那么找他的子节点的范围就在 [1, nums[i]) 这个范围内。对于一个潜在的 node.val nums[i],我们要找的是数组内是否含有一个 nums[j] 满足 nums[i] % nums[j] == 0 同时 nums[i] / nums[j] 也在 hashmap 中。如果有这样的组合,那么说明我们就能构建一棵符合题意的树。记得最后要对结果取模。

注意每个节点都可以当做叶子节点,这也就是为什么 hashmap 创建之后可以把所有元素都放入 hashmap 并把 value 标记为 1 的原因。

举例,如果父节点 val = 8,同时也有 val = 2 和 val = 4,我们可以组成的子树有两棵,一棵是 2 在左子树,4 在右子树;另一棵是反过来,4 在左子树,2 在右子树。代码在这里计算的时候因为当我去找比 8 小的元素的时候,如果 i 的循环里找到 2,那么 j 的循环里就一定能找到 4,反之 i 的循环里找到 4,j 的循环里能找到 2,所以这里不会漏解。如果是比如 arr[i] == arr[j] 的时候,则只会被计算一次,因为左右子树 val 相等。

时间O(n^2)

空间O(n)

Java实现

 1 class Solution {
 2     public int numFactoredBinaryTrees(int[] nums) {
 3         // corner case
 4         if (nums == null || nums.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int MOD = (int) Math.pow(10, 9) + 7;
10         int len = nums.length;
11         long res = 0;
12         Arrays.sort(nums);
13         HashMap<Integer, Long> map = new HashMap<>();
14         // 每个数字默认都可以组成一个以自己为根节点的树
15         for (int num : nums) {
16             map.put(num, 1L);
17         }
18 
19         for (int i = 0; i < len; i++) {
20             long count = map.get(nums[i]);
21             for (int j = 0; j < i; j++) {
22                 // 如果j能被i整除同时i / j的商也在hashmap中,那么就可以累加
23                 if (nums[i] % nums[j] == 0 && map.containsKey(nums[i] / nums[j])) {
24                     count += map.get(nums[j]) * map.get(nums[i] / nums[j]);
25                 }
26             }
27             map.put(nums[i], count);
28             res = (res + count) % MOD;
29         }
30         return (int) res;
31     }
32 }

 

LeetCode 题目总结

posted @ 2020-11-26 07:33  CNoodle  阅读(259)  评论(0编辑  收藏  举报