343. 整数拆分
代码随想录视频讲解:动态规划,本题关键在于理解递推公式!| LeetCode:343. 整数拆分_哔哩哔哩_bilibili
解题思路
1. dp[i]对i进行拆分,得到的最大的乘积为dp[i]
2.递推公式
一个是j * (i - j) 直接相乘,拆为两个数
一个是j * dp[i - j],相当于是拆分(i - j),拆为三个或以上
dp[i] = max(上面两个)
3.初始化
dp[0] = 0;
dp[1] = 0;
dp[2] = 1;
4.遍历顺序从i=3开始遍历,直接到n,而j只需要遍历到i/2即可,因为乘积最大只会出现在数尽可能相同的情况下
class Solution {
public:
int integerBreak(int n) {
vector<int> dp(n+1);
dp[0] =0;
dp[1] = 0;
dp[2] = 1;
for(int i=3 ; i<=n ; i++)
{
for(int j =1; j<=(i/2);j++ )
{
dp[i] = dp[i]>max(j*(i-j),j*dp[i-j]) ? dp[i] : max(j*(i-j),j*dp[i-j]) ;
}
}
return dp[n];
}
};
- 时间复杂度:O(n^2)
- 空间复杂度:O(n)
96.不同的二叉搜索树
代码随想录视频讲解:动态规划找到子状态之间的关系很重要!| LeetCode:96.不同的二叉搜索树_哔哩哔哩_bilibili
解题思路
当n为3的时候,那么就有头结点为1,2,3的情况
头1 = 左子树0节点元素情况 * 右子树2节点元素的情况
头2 = 左子树1节点 * 右子树1节点
头3 = 左子树2节点 * 右子树0节点
dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]
1.dp[i] 表示 i为节点个数,dp[i]表示有多少个二叉搜索树
2.例如以j为头结点,左子树有j-1个节点,右子树有i-j个节点,一共是i个节点(二叉搜索树的特性)
dp[i] += dp[j-1] * dp[i-j] 不同头结点的情况是相加起来的
3.初始化
dp[0] =1 空节点也算是一个子树,且是符合递推公式的
dp[1] =1
dp[i] =0
4.遍历顺序
dpi都是由比他小的节点个数推导而来
class Solution {
public:
int numTrees(int n) {
if(n<=1) return 1;
vector<int> dp(n+1,0);
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];
}
};
收获
动态规划太难了