mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-06 01:15:57 +08:00
Add solution 823
This commit is contained in:
@ -0,0 +1,70 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
const mod = 1e9 + 7
|
||||
|
||||
// 解法一 DFS
|
||||
func numFactoredBinaryTrees(arr []int) int {
|
||||
sort.Ints(arr)
|
||||
numDict := map[int]bool{}
|
||||
for _, num := range arr {
|
||||
numDict[num] = true
|
||||
}
|
||||
dict, res := make(map[int][][2]int), 0
|
||||
for i, num := range arr {
|
||||
for j := i; j < len(arr) && num*arr[j] <= arr[len(arr)-1]; j++ {
|
||||
tmp := num * arr[j]
|
||||
if !numDict[tmp] {
|
||||
continue
|
||||
}
|
||||
dict[tmp] = append(dict[tmp], [2]int{num, arr[j]})
|
||||
}
|
||||
}
|
||||
cache := make(map[int]int)
|
||||
for _, num := range arr {
|
||||
res = (res + dfs(num, dict, cache)) % mod
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func dfs(num int, dict map[int][][2]int, cache map[int]int) int {
|
||||
if val, ok := cache[num]; ok {
|
||||
return val
|
||||
}
|
||||
res := 1
|
||||
for _, tuple := range dict[num] {
|
||||
a, b := tuple[0], tuple[1]
|
||||
x, y := dfs(a, dict, cache), dfs(b, dict, cache)
|
||||
tmp := x * y
|
||||
if a != b {
|
||||
tmp *= 2
|
||||
}
|
||||
res = (res + tmp) % mod
|
||||
}
|
||||
cache[num] = res
|
||||
return res
|
||||
}
|
||||
|
||||
// 解法二 DP
|
||||
func numFactoredBinaryTrees1(arr []int) int {
|
||||
dp := make(map[int]int)
|
||||
sort.Ints(arr)
|
||||
for i, curNum := range arr {
|
||||
for j := 0; j < i; j++ {
|
||||
factor := arr[j]
|
||||
quotient, remainder := curNum/factor, curNum%factor
|
||||
if remainder == 0 {
|
||||
dp[curNum] += dp[factor] * dp[quotient]
|
||||
}
|
||||
}
|
||||
dp[curNum]++
|
||||
}
|
||||
totalCount := 0
|
||||
for _, count := range dp {
|
||||
totalCount += count
|
||||
}
|
||||
return totalCount % mod
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type question823 struct {
|
||||
para823
|
||||
ans823
|
||||
}
|
||||
|
||||
// para 是参数
|
||||
// one 代表第一个参数
|
||||
type para823 struct {
|
||||
arr []int
|
||||
}
|
||||
|
||||
// ans 是答案
|
||||
// one 代表第一个答案
|
||||
type ans823 struct {
|
||||
one int
|
||||
}
|
||||
|
||||
func Test_Problem823(t *testing.T) {
|
||||
|
||||
qs := []question823{
|
||||
|
||||
{
|
||||
para823{[]int{2, 4}},
|
||||
ans823{3},
|
||||
},
|
||||
|
||||
{
|
||||
para823{[]int{2, 4, 5, 10}},
|
||||
ans823{7},
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Printf("------------------------Leetcode Problem 823------------------------\n")
|
||||
|
||||
for _, q := range qs {
|
||||
_, p := q.ans823, q.para823
|
||||
fmt.Printf("【input】:%v 【output】:%v\n", p, numFactoredBinaryTrees(p.arr))
|
||||
}
|
||||
fmt.Printf("\n\n\n")
|
||||
}
|
119
leetcode/0823.Binary-Trees-With-Factors/README.md
Normal file
119
leetcode/0823.Binary-Trees-With-Factors/README.md
Normal file
@ -0,0 +1,119 @@
|
||||
# [823. Binary Trees With Factors](https://leetcode.com/problems/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] <= 10^9`
|
||||
|
||||
## 题目大意
|
||||
|
||||
给出一个含有不重复整数元素的数组,每个整数均大于 1。我们用这些整数来构建二叉树,每个整数可以使用任意次数。其中:每个非叶结点的值应等于它的两个子结点的值的乘积。满足条件的二叉树一共有多少个?返回的结果应模除 10 * 9 + 7。
|
||||
|
||||
## 解题思路
|
||||
|
||||
- 首先想到的是暴力解法,先排序,然后遍历所有节点,枚举两两乘积为第三个节点值的组合。然后枚举这些组合并构成树。这里计数的时候要注意,左右孩子如果不是对称的,左右子树相互对调又是一组解。但是这个方法超时了。原因是,暴力枚举了很多次重复的节点和组合。优化这里的方法就是把已经计算过的节点放入 `map` 中。这里有 2 层 `map`,第一层 `map` 记忆化的是两两乘积的组合,将父亲节点作为 `key`,左右 2 个孩子作为 `value`。第二层 `map` 记忆化的是以 `root` 为根节点此时二叉树的种类数,`key` 是 `root`,`value` 存的是种类数。这样优化以后,DFS 暴力解法可以 runtime beats 100%。
|
||||
- 另外一种解法是 DP。定义 `dp[i]` 代表以 `i` 为根节点的树的种类数。dp[i] 初始都是 1,因为所有节点自身可以形成为自身单个节点为 `root` 的树。同样需要先排序。状态转移方程是:
|
||||
|
||||
$$dp[i] = \sum_{j<i, k<i}^{}dp[j] * dp[k], j * k = i$$
|
||||
|
||||
最后将 `dp[]` 数组中所有结果累加取模即为最终结果,时间复杂度 O(n^2),空间复杂度 O(n)。
|
||||
|
||||
## 代码
|
||||
|
||||
```go
|
||||
package leetcode
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
const mod = 1e9 + 7
|
||||
|
||||
// 解法一 DFS
|
||||
func numFactoredBinaryTrees(arr []int) int {
|
||||
sort.Ints(arr)
|
||||
numDict := map[int]bool{}
|
||||
for _, num := range arr {
|
||||
numDict[num] = true
|
||||
}
|
||||
dict, res := make(map[int][][2]int), 0
|
||||
for i, num := range arr {
|
||||
for j := i; j < len(arr) && num*arr[j] <= arr[len(arr)-1]; j++ {
|
||||
tmp := num * arr[j]
|
||||
if !numDict[tmp] {
|
||||
continue
|
||||
}
|
||||
dict[tmp] = append(dict[tmp], [2]int{num, arr[j]})
|
||||
}
|
||||
}
|
||||
cache := make(map[int]int)
|
||||
for _, num := range arr {
|
||||
res = (res + dfs(num, dict, cache)) % mod
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func dfs(num int, dict map[int][][2]int, cache map[int]int) int {
|
||||
if val, ok := cache[num]; ok {
|
||||
return val
|
||||
}
|
||||
res := 1
|
||||
for _, tuple := range dict[num] {
|
||||
a, b := tuple[0], tuple[1]
|
||||
x, y := dfs(a, dict, cache), dfs(b, dict, cache)
|
||||
tmp := x * y
|
||||
if a != b {
|
||||
tmp *= 2
|
||||
}
|
||||
res = (res + tmp) % mod
|
||||
}
|
||||
cache[num] = res
|
||||
return res
|
||||
}
|
||||
|
||||
// 解法二 DP
|
||||
func numFactoredBinaryTrees1(arr []int) int {
|
||||
dp := make(map[int]int)
|
||||
sort.Ints(arr)
|
||||
for i, curNum := range arr {
|
||||
for j := 0; j < i; j++ {
|
||||
factor := arr[j]
|
||||
quotient, remainder := curNum/factor, curNum%factor
|
||||
if remainder == 0 {
|
||||
dp[curNum] += dp[factor] * dp[quotient]
|
||||
}
|
||||
}
|
||||
dp[curNum]++
|
||||
}
|
||||
totalCount := 0
|
||||
for _, count := range dp {
|
||||
totalCount += count
|
||||
}
|
||||
return totalCount % mod
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user