代码随想Day41 | 343. 整数拆分、96.不同的二叉搜索树

343. 整数拆分 

这道题的贪心思路是尽可能地拆分成3,(结论),需要进行数学证明,详细代码如下:

class Solution {
public:
    int integerBreak(int n) {
        if(n==2) return 1;
        if(n==3) return 2;
        if(n==4) return 4;
        int res = 1;
        while(n>4)
        {
            res*=3;
            n-=3;
        }
        res*=n;
        return res;

    }
};

动态规划的思路为:

确定dp数组(dp table)以及下标的含义:dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。

确定递推公式:

从1遍历j,然后有两种渠道得到dp[i],一个是j * (i - j) 直接相乘,一个是j * dp[i - j],相当于是拆分(i - j)。j怎么就不拆分呢?j是从1开始遍历,拆分j的情况,在遍历j的过程中其实都计算过了。那么从1遍历j,比较(i - j) * j和dp[i - j] * j 取最大的。所以递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j))。其余步骤省略~详细代码如下:

class Solution {
public:
    int integerBreak(int n) {
        vectordp(n+1);
        dp[2]=1;
        for(int i=3;i<=n;i++)
        {
            for(int j=1;j

96.不同的二叉搜索树 

这道题的递推思路比较难想到,先看代码随想录进行学习:

来看n为3的时候情况。

当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]

代码随想Day41 | 343. 整数拆分、96.不同的二叉搜索树_第1张图片

详细代码如下:

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

    }
};

你可能感兴趣的:(好好刷leetcode,算法)