代码随想录算法训练营第41天|343. 整数拆分、96.不同的二叉搜索树

文章目录

  • 343. 整数拆分
    • 思路
    • 代码
  • 96.不同的二叉搜索树
    • 思路
    • 代码

343. 整数拆分

题目链接:343. 整数拆分
文章讲解:代码随想录|343. 整数拆分
视频讲解:整数拆分

思路

1.dp[i]:整数i拆分成k个数的最大乘积

2.dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j)):
从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的
(i - j) * j是拆成两个数,dp[i - j] * j 是拆成3个或更多
dp[i - j]肯定比dp[i]要小,之前已经求出来了
比如数字10,可以拆成
1x9
2x8
3x7,7可以拆成3x4等等,4可以拆成2x2等等(不拆3x7中的3是因为拆3的情况肯定在拆1x9和2x8的时候出现过)
4x6
5x5

3.dp[2] = 1
4.从前向后遍历
5.举例

代码

class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n + 1);
        dp[2] = 1;
        for (int i = 3; i <= n ; i++) {
            for (int j = 1; j <= i / 2; j++) {
                dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
            }
        }
        return dp[n];
    }
};

j为什么不从i/2 开始遍历:因为当需要拆成3个及以上的数值相似的数时,j就小于i/2了

96.不同的二叉搜索树

题目链接:96.不同的二叉搜索树
文章讲解:代码随想录|96.不同的二叉搜索树
视频讲解:96.不同的二叉搜索树

思路

一开始看比较懵,可以先举几个例子,看看有没有规律
代码随想录算法训练营第41天|343. 整数拆分、96.不同的二叉搜索树_第1张图片
代码随想录算法训练营第41天|343. 整数拆分、96.不同的二叉搜索树_第2张图片当1为头结点的时候,其右子树有两个节点,看这两个节点的布局,是不是和 n 为2的时候两棵树的布局是一样的啊!

(可能有同学问了,这布局不一样啊,节点数值都不一样。别忘了我们就是求不同树的数量,并不用把搜索树都列出来,所以不用关心其具体数值的差异)

当3为头结点的时候,其左子树有两个节点,看这两个节点的布局,是不是和n为2的时候两棵树的布局也是一样的啊!

当2为头结点的时候,其左右子树都只有一个节点,布局是不是和n为1的时候只有一棵树的布局也是一样的啊!

发现到这里,其实我们就找到了重叠子问题了,其实也就是发现可以通过dp[1] 和 dp[2] 来推导出来dp[3]的某种方式。
dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量

元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量

元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量

元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量

有2个元素的搜索树数量就是dp[2]。

有1个元素的搜索树数量就是dp[1]。

有0个元素的搜索树数量就是dp[0]。

所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]
代码随想录算法训练营第41天|343. 整数拆分、96.不同的二叉搜索树_第3张图片

  1. dp[i] : 1到i为节点组成的二叉搜索树的个数为dp[i]
  2. 所以递推公式:dp[i] += dp[j - 1] * dp[i - j]; j相当于是头结点的元素,从1遍历到i为止。j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量
  3. dp[0] = 1
  4. 遍历i里面每一个数作为头结点的状态,用j来遍历。
  5. 举例

代码

class Solution {
public:
    int numTrees(int n) {
        vector<int> dp(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];
    }
};

你可能感兴趣的:(算法)