【算法】动态规划系列3-力扣2题(343、96)

136 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

做动态规划的第三天,明显难度上升

343 整数拆分

给定一个正整数 n ,将其拆分为 k正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回 你可以获得的最大乘积

题目给的例子:

 示例 1:
 输入: n = 2
 输出: 1
 解释: 2 = 1 + 1, 1 × 1 = 1
 ​
 ​
 示例 2:
 输入: n = 10
 输出: 36
 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

1.新建一个dp二维数组

因为正整数n,所以取n+1,要不然根据下标会少一个数

2.分析公式:

由例子得,比如10,可以拆分成

10=1+9,2+8,3+7,4+6,5+5 后面就是两个数字相反,乘积还是相同

还可以再拆,10=3+7,7=1+6,2+5,3+4,推出 10=3+(3+4)

由此可得分为两种

a.一种是直接拆开,不拆第二次

b.已经拆开,继续拆

所以dp[i],需要从1开始遍历j,有上述两种方式得到dp[i]

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

有一种特殊情况,就是要比原有得数字大,才满足题意,所以修改如下

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

3.初始化

dp[1] = 1;

dp[2] = 1;

所以循环i可以从3开始

4.完整代码

 public int integerBreak(int n) {
         int[] dp = new int[n+1];
         dp[2] = 1;
         dp[1] = 1;
         for(int i=3;i<=n;i++){
             for(int j=1;j<i-1;j++){
                 dp[i] = Math.max(dp[i],Math.max(j*dp[i-j],j*(i-j)));
             }
         }
         return dp[n];
 }
96 不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

96 题.png

 输入:n = 3
 输出:5

示例 2:

 输入:n = 1
 输出:1

思路:

1.新建一个dp二维数组

n个节点,且n=0的时候,虽然是一个二叉树,但是没有意义

2.分析公式:

以n=3为例,root节点为1时,总数= 右子树有2个元素的搜索树的数量*左子树有0个元素的搜索树数量

root节点为2时,总数=右子树有1个元素的搜索树的数量*左子树有1个元素的搜索树数量

root节点为3时,总数=右子树有0个元素的搜索树的数量*左子树有3个元素的搜索树数量

换成公式为: dp[1] =dp[2]*dp[0]

dp[2] =dp[1]*dp[1]

dp[3] =dp[0]*dp[2]

可以看出规律,假设root节点为i,那么左子树的范围一定是(1,i-1),因为是二叉搜索树

所以右子树范围一定是(i+1,n),所以,左子树的个数为i-1,右子树的个数为n-i

那么就转化求:dp[i-1]*dp[n-i]

 dp[i] += dp[j-1]*dp[i-j]

3.初始化

dp[0] = 1; 虽然是一个二叉树,但是没有意义

dp[1] = 1;

4.完整代码

 public int numTrees(int n) {
         int[] dp = new int[n+1];
         dp[0]=1;
         dp[1]=1;
         for(int i=2;i<=n;i++){
             for(int j=1;j<=i;j++){
                 dp[i] += dp[j-1]*dp[i-j];
             }
         }
         return dp[n];
     }