算法训练day40-动态规划-整数拆分、不同的二叉搜索树

343. 整数拆分

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

  • 输入: 2

  • 输出: 1

  • 解释: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

  • 输入: 10

  • 输出: 36

  • 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

  • 说明: 你可以假设 n 不小于 2 且不大于 58。

解题思路

  1. 定义动态规划数组dp[i]

表示对于正整数i拆分后的最大乘积

  1. 确定递推公式

对于正整数i,怎样拆分能得到最大的乘积呢?

通过一些数学上的证明发现,当拆分后的各个数字大小接近时,乘积较大。

所以按照这个思路需要将i尽可能的拆分为大小接近的2个及以上的数子,然后再依次比较找到最大乘积。

假如dp[i] 拆分为两个数字,则可以表示为

j*(i-j)

如果拆分为三个及以上的数字,则可以表示为

j*dp[i-j]

由此可以得出递推公式为:

dp[i] = max({dp[i], (i - j) * j, dp[i - j] * j})

  1. dp数组初始化

因为dp[0]和dp[1] 没有意义,所以i 从3开始,j从1开始,只需要初始化dp[2]。

dp[2] = 1

代码实现-java

class Solution {
    public int integerBreak(int n) {
        // 定义dp数组
        int[] dp = new int[n+1];
        // 初始化
        dp[2] = 1;
        // 遍历
        for(int i=3;i<=n;i++){
            // j 最大值为 i-j,再大只不过是重复而已
            for(int j=1;j<=i-j;j++){
                dp[i] = Math.max(dp[i],Math.max(j*dp[i-j],j*(i-j)));
            }
        }
        return dp[n];
    }
}

96.不同的二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

解题思路

什么是二叉搜索树?

二叉搜索树是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

  • 它的左、右子树也分别为二叉搜索树

当n =1时,只有一颗搜索树

当n=2时,有两颗搜索树

当n=3时,

如果1为头结点,那么2和3只能都在右子树上,对于右子树的布将于n=2的布局相同

如果2为头结点,那么1只能在左子树,3只能在右子树,左右子树各有一个节点,与n=1的布局相似

如果3为头结点,那么1,2只能在左子树,此时左子树布局相当于n=2的布局

从以上分析就能发现一些规律,n=3的布局其实可以由n=1和n=2推导出来

定义dp[i]数组:表示n=i时,以1...i组成的二叉搜索树的数量

其推导公式为:dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

  1. 所以可以得到递推公式:dp[i] += dp[j - 1] * dp[i - j] (j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量)

  1. dp数组初始化

dp[0] = 1(可以认为空节点也是一颗二叉搜索树)

  1. 确定遍历顺序

从小到大遍历节点数

代码实现-java

class Solution {
    public int numTrees(int n) {
       // 定义dp数组
       int[] dp = new int[n+1];
       // 初始化
       dp[0] = 1;
       // 遍历
       for(int i=1;i<=n;i++){
          for(int j=1;j<=i;j++){
              dp[i] += dp[j-1] * dp[i-j];
          }
       }
       return dp[n];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值