823. 带因子的二叉树 - Kotlin 动态规划+双指针
                
            
             
        
            
            
Problem: 823. 带因子的二叉树 
思路
设dp[i]为以arr[i]为根节点能够构建出的二叉树数量,对于任意a、b满足arr[a]*arr[b]==arr[i],考虑以下两种情况:
- 当
a==b时,能够构建出的二叉树数量为dp[a]*dp[b] 
- 当
a!=b时,能够构建出的二叉树数量为dp[a]*dp[b]*2,因为a和b可以调换左右位置形成一轮新的组合情况,而当a==b时调换左右位置是没有意义的 
由于数据范围规定了arr[i]>=2,能够保证满足arr[a]*arr[b]==arr[i]的a和b必定在这个范围中,考虑到后效性,我们将arr进行升序排序,这样当我们遍历到arr[i]时,保证任意索引大于i的元素都不会影响到dp[i]的计算
与此同时,当我们用双指针遍历查找满足arr[a]*arr[b]==arr[i]的a和b时,由于数组是升序排序的,当arr[a]*arr[b]>arr[i]时,右指针继续右移只会让乘积越来越大,可以直接break
复杂度
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | class Solution  fun Solution.numFactoredBinaryTrees(arr: IntArray): Int {     val dp = LongArray(arr.size) { 1 }     arr.sort()     for ((index, value) in arr.withIndex()) {         for (left in 0..index) {             for (right in left..index) {                 if ((arr[left]).toLong() * (arr[right]).toLong() == (value).toLong()) {                     dp[index] = (dp[index] + dp[left] * dp[right] * (if (left != right) 2 else 1)) % (1e9 + 7).toLong()                 } else if ((arr[left]).toLong() * (arr[right]).toLong() > (value).toLong()) {                     break                 }             }         }     }     return (dp.fold((0).toLong()) { sum, value -> (sum + value) % (1e9 + 7).toLong() }).toInt() }
 
   |