动态规划-整数拆分,不同的二叉搜索树

120 阅读2分钟

整数拆分

image.png

根据题意,一个整数可以被拆分成两个以上的数,求拆分之后能获得的最大乘积。

  1. 首先分析dp[i]数组的含义:dp[i]应该表示整数i拆分之后的最大乘积

  2. dp数组定义:我们求整数i的最大乘积的思路是使用两层for循环,从1开始拆分,遍历所有的可能性,举例来说当n=6,逐一拆分成(1,5)(2,4)(3,3),求其乘积最大值。所以dp数组定义为

    dp[i] = Math.max(dp[i],Math.max(j * (i - j),j * dp[i - j]));

    j*(i - j)表示将整数拆分成两个数,j * dp[i - j]表示将整数拆分成两个以上的数,dp[i]表示求循环过程中dp[i]的最大值

  3. dp数组初始化,显然dp[0],dp[1]拆分无意义,所以不进行初始化定义,定义dp[2]=1

  4. 遍历方向,显然是从左往右遍历

image.png

可以看到j遍历到i/2的位置就停止遍历了,这是因为

如果m表示能实现整数乘积最大化的拆分的乘数的数量, 最大值一般出现在n/m值附近,比如n=10,最大值是3*3*4,在10/3附近, 所以遍历j的时候,遍历到m=2,即n/2的位置就可以了,即将整数拆分成两个数,剩下的继续遍历的接结果肯定没有中间位置乘积大

不同的二叉搜索树

image.png

image.png

可以观察一下n=3的时候的树的规则,当头节点值为1,只有右子树,右子树的规则和n=2时二叉搜索树的形态相同,头节点值为2,左右各有一个子树,规则和n=1时二叉搜索树的形态相同,同理n=3时的情况。

1.dp[i]定义:i个节点形成的子树的个数

2.dp[i] = dp[i-j-1] * dp[j],i表示节点总数,j表示左子树节点数量

3.dp[0]无意义,后面相乘的时候应该作为1,所以定义为1;dp[1]只有一种子树

4.遍历方向:从左往右
image.png