Day41 | 343. 整数拆分, 96.不同的二叉搜索树
重点在于对递推公式的理解,即子状态继承的理解!
整数拆分
LeetCode题目:https://leetcode.cn/problems/integer-break/
整体思路
按照五步进行分析,dp数组在本题目中的含义为整数n的最大乘积。对于第n个数的最大乘积,存在两种情况,一种是得到一个i值,i ∗ * ∗dp[n-i];另一种情况是dp[i] < < <i,此时i*(n-i)。循环得到的最大值即是所求最大值。
最后,根据递推公式可以执行正序的遍历。
class Solution {
public:
int integerBreak(int n) {
/* 保存第k个数的最大乘积 */
vector<int> dp(n+1,0);
dp[0] = 0;
dp[1] = 0;
dp[2] = 1;
for (int i = 3;i <= n;i++) {
for (int j = 1;j < i;j++ ) {
dp[i] = max(max(j*dp[i-j],j*(i-j)),dp[i]);
}
}
return dp[n];
}
};
不同的二叉搜索树
LeetCode题目:https://leetcode.cn/problems/unique-binary-search-trees/
解题思路
该题主要考察对二叉搜索树的理解。dp数组确定自然是代表n个节点可以构成的二叉搜索树的个数。一个节点和两个节点的情况很容易进行初始化,到三个点的时候情况就开始复杂。可以抽象为,当取最小值的时候,剩下n-1个节点都在右子树,此时考虑左子树0个节点可以构成的个数*右子树n-1个节点可以构成二叉搜索树的个数。
依次递推,到第i个节点为左子树i-1个节点排列个数 ∗ * ∗右侧n-1-i个节点排列个数。
确定遍历方法,由于每个dp的条件应该由之前的子状态确定,因此需要进行正序遍历。
代码如下:
class Solution {
public:
int numTrees(int n) {
if(n==1) return 1;
vector<int> dp(n+1,0);
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for (int i = 3;i <= n;i++) {
for(int j = 0 ;j < i;j++){
dp[i] += dp[j]*dp[i-1-j];
}
}
return dp[n];
}
};