代码随想录打卡—day41—【DP】— 8.26+27 DP基础3

1 343. 整数拆分

343. 整数拆分

一开始做 没有思路,学习了题解才,ac代码:

class Solution {
public:
    int dp[60];  // 含义:i 把它拆分成若干个数,这些数的乘积最大的值
    /*
    很妙这里j的含义 ,如果是我直觉会用k作为其中一个循环 但不知道是不是要三个循环...
    j的含义i的拆分因子: 因为k大于等于2 所以至少两个因子 所以 j = 1,...,i-1
    dp[i] = max(dp[i], max(j*(i-j) , dp[i-j]*j))
                        拆分成两个  拆分2个以上
    dp[2] = 1;
    i++


    2 3 4 5 6
    1 2 4 
    */
    int integerBreak(int n) 
    {
        dp[2] = 1;
        if(n == 2)return dp[2];

        for(int i = 3; i <= n; i++)
            for(int j = 1; j <= i-1;j++)
                dp[i] = max(dp[i], max(j*(i-j) , dp[i-j]*j));
                
        return dp[n];

    }
};

后来仔细看题解,其实 for - j 的次数可以优化——


注意 枚举j的时候,是从1开始的。从0开始的话,那么让拆分一个数拆个0,求最大乘积就没有意义了。

优化1:

j 的结束条件是 j < i - 1 ,其实 j < i 也是可以的,不过可以节省一步,例如让j = i - 1,的话,其实在 j = 1的时候,这一步就已经拆出来了,重复计算,所以 j < i - 1

至于 i是从3开始,这样dp[i - j]就是dp[2]正好可以通过我们初始化的数值求出来。

优化2: 更优化一步,可以这样:

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));
    }
}

因为拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的。

例如 6 拆成 3 * 3, 10 拆成 3 * 3 * 4。 100的话 也是拆成m个近似数组的子数 相乘才是最大的。

只不过我们不知道m究竟是多少而已,但可以明确的是m一定大于等于2,既然m大于等于2,也就是 最差也应该是拆成两个相同的 可能是最大值。

那么 j 遍历,只需要遍历到 n/2 就可以,后面就没有必要遍历了,一定不是最大值。

至于 “拆分一个数n 使之乘积最大,那么一定是拆分成m个近似相同的子数相乘才是最大的” 这个我就不去做数学证明了,感兴趣的同学,可以自己证明。


题解的贪心做法:

本题也可以用贪心,每次拆成n个3,如果剩下是4,则保留4,然后相乘,但是这个结论需要数学证明其合理性!

2 96. 不同的二叉搜索树

96. 不同的二叉搜索树

看到题目一开始又是懵的,看了题解才知道从n=1 n=2 到n=3可以借助前n=1,n=2推出来,找到规律,AC代码:

class Solution {
public:
    int dp[20];  // 恰由i个节点组成的不同的二叉线索树最大的数目
    /*
    dp[0] = 0;
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = dp[0]*dp[2] + dp[1]*dp[1] + dp[2]*dp[0]

    for(int j = 1; j <= i; j++)
        dp[i] += dp[j-1]*dp[n-j];
    
    i++

    0 1 2 3 4
    0 1 2 5 

    */
    int numTrees(int n) 
    {
        dp[0] = 1;  // 没有实际含义 为了凑结果的
        dp[1] = 1;
        dp[2] = 2;

        for(int i = 3; i <= n; i++)
            for(int j = 1;j <= i; j++)
                dp[i] += dp[j-1]*dp[i-j];
        
        return dp[n];
    }
};

你可能感兴趣的:(SXL,算法,动态规划,leetcode)