当前位置:网站首页>七夕力扣刷不停,343. 整数拆分(剑指 Offer 14- I. 剪绳子、剑指 Offer 14- II. 剪绳子 II)

七夕力扣刷不停,343. 整数拆分(剑指 Offer 14- I. 剪绳子、剑指 Offer 14- II. 剪绳子 II)

2022-08-09 12:46:00 byte字节8位-128~127

https://leetcode-cn.com/problems/integer-break/
https://leetcode-cn.com/problems/jian-sheng-zi-lcof/

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

根据以上思路得动态规划状态转移方程dp表达式
dp[n] = max(dp[n],dp[j]*dp[n-j]);
这里解释一下,就是可以选择直接是dp[n],或者将dp[n]划分为两个数,看这两个数的乘积和不划分的dp[n],这两个哪个比较大。
有时候划分了可能会变小,比如dp[2],dp[3]
dp6中可能包括多个dp[2]或者3,所以,这个时候就要考虑,是否要继续划分的问题。
dp[n]:长度为n的数获得的乘积的最大值

class Solution {
    
    public int integerBreak(int n) {
    
        //动态规划
        //base case
        int[] dp = new int[n+1];
        if(n<2){
    
            return 1;
        }
        if(n==2){
    
            return 1;
        }
        if(n==3){
    
            return 2;
        }
        //这里要说明一下,因为对于2、3,再拆分就会越来越小,
        //所以就不拆分了,只要答案对就行,也不能太纠结
        dp[1]=1;
        dp[2]=2;
        dp[3]=3;
		//双层for循环,动态规划经典标志
        for(int i=4;i<=n;i++){
    
            for(int j=1;j<=(i/2);j++){
    
                dp[i] = Math.max(dp[i],dp[j]*dp[i-j]);
            }
        }
        return dp[n];
    }
}
class Solution {
    
    public int integerBreak(int n) {
    
    if(n<=2){
    
            return 1; 
        }
        if(n==3){
    
            return 2;
        }

        int[] dp = new int[n+1];
        //基础的就不分了,因为会越分越小
        dp[1]=1;dp[2]=2;dp[3]=3;
        // dp[1]=1;
        // dp[2]=2;
        // dp[3]=3;
        for(int i=4;i<=n;i++){
    
            for(int j=1;j<=(i/2);j++){
    
                dp[i] = Math.max(dp[i],dp[j]*dp[i-j]);
            }
        }
        return dp[n];
    }
}


代码一样,只是出现了一个bug,调试一下,就好了

class Solution {
    
    public int cuttingRope(int n) {
    
        int[] dp = new int[n+1];
        if(n<=2){
    
            return 1;
        }
        if(n==3){
    
            return 2;
        }
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        //双层for循环,经典动态规划标志
        for(int i=4;i<=n;i++){
    
        //这里的j忘记写=了
            for(int j=1;j<=(i/2);j++){
    
                System.out.println(dp[i]);
                System.out.println(dp[j]*dp[i-j]);
                dp[i] =  Math.max(dp[i],dp[j]*dp[i-j]);
                System.out.println(dp[i]);
            }
        }
        return dp[n];
    }
}

参考链接:
LeetCode每日打卡.343.整数拆分

剑指 Offer 14- II. 剪绳子 II
https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof/solution/wu-xu-fu-za-shu-xue-jiang-jie-dong-tai-g-j470/

class Solution {
    
public:
    int cuttingRope(int n) {
    
        if (n < 4) {
    
            return n - 1;
        }
        vector<int> products(n + 1, 0);
        products[1] = 1;
        products[2] = 2;
        products[3] = 3;
        int maxVal = 0;
        for (int i = 4; i <= n; ++i) {
    
            maxVal = 0;
            for (int j = 1; j <= i / 2; ++j) {
    
                maxVal = max(maxVal, products[j] * products[i - j]);
            }
            products[i] = maxVal;
        }
        return products[n];
    }
};
class Solution {
    
    public int cuttingRope(int n) {
    
        /** 思路:动态规划 费曼学习法一遍 动态规划是一种穷举,然后可以避免我们重复计算 我们先自上而下考虑: 比如,对于一个绳子n,我们可以先切一刀 然后,获取两段,那么我们可以有n-1种切法,因为n要求是整数 然后可以对其中一段,再进行切 获取若干段,不断重复这个过程 最后直到分为不可以再分的段数,然后我们 再自下而上的考虑: 然后根据求出的每段的最大值,来考虑该段是否需要进行划分 由于有一些边界条件限制,所以我们应该先初始化 */
        
        if(n<2){
    
            return 1;
        }   
        if(n==2){
    
            return 1;
        }
        if(n==3){
    
            return 2; 
        }
       
        int[] dp = new int[n+1];
        //由公式可以证明,当n小于4的时候,不分开获取的结果会更大一些
        //我们的dp数组,就是按照不分开进行计算的
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;
        //穷举每一种可能
        for(int i=4;i<=n;i++){
    
            //每一种可能是否需要划分
            for(int j=1;j<=(i/2);j++){
    
                //是否划分,划分后大还是不划分大,整一个for循环,来寻找dp[i]的最大值
                dp[i] = Math.max(dp[i],dp[j]*dp[i-j]);
            }
        } 
        return dp[n];
    }
}
原网站

版权声明
本文为[byte字节8位-128~127]所创,转载请带上原文链接,感谢
https://blog.csdn.net/dd_Mr/article/details/126178557