leetcode 143 整数拆分

这篇博客探讨了如何解决一个数学问题:给定一个正整数n,将其拆分为若干正整数的和,以最大化这些整数的乘积。作者通过示例解释了问题背景,并提供了三种不同的解决方案:递归自顶向下、记忆化搜索和动态规划。每种方法都以Java代码的形式展示,并讨论了它们的时间复杂度和适用场景。递归方法可能会导致超时,因此引入了备忘录以提高效率。动态规划方法通过填充一个数组来避免重复计算,从而达到优化的目的。
摘要由CSDN通过智能技术生成

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

因为n可以拆分成两个数,也可以拆分多个数。 拆分成两个数的时候乘积就是i * (n - i),也可以选择继续拆分:integerBreak(n - i)就是将n - i继续拆分的结果,但是我们并不知道种哪拆分的结果更大,所以我们要取二者的较大值作为当前拆分的最大值。

class Solution {
    int n;
    int ans;
    public int integerBreak(int n) {
        this.n=n;
        dfs(1,0,1);
        return ans;
    }
    void dfs(int start,int sum,int mult){
        if(sum==n){
            if(mult>ans) ans=mult;
            return ;
        }
        for(int i=start;i<=n-1;i++){
            if(sum+i>n) break;
            dfs(i,sum+i,mult*i);
        }
    }
}

递归自顶向下容易超时,所以再加上一个备忘录。
这个备忘录可以是HashMap也可以是数组。

class Solution {
    HashMap<Integer,Integer> hash=new HashMap<>();
    public int integerBreak(int n) {
        if(n==2) return 1;
        //如果有key值n,就直接返回value
        if(hash.containsKey(n)) return hash.get(n);
        //下面是没有key,就要计算,然后加入到hash中
        int res=-1;
        for(int i=1;i<=n-2;i++){
            res=Math.max(res,Math.max((n-i)*i,integerBreak(n-i)*i));
        }
        hash.put(n,res);
        return res;
    }
}

因为memory需要分配内存,不可能再递归函数里面分配,所有要再加一个函数

class Solution {
// 记忆化搜索-自顶向下
int[] memory;
//因为memory需要分配内存,不可能再递归函数里面分配,所有要再加一个函数
public int integerBreak(int n) {
    memory = new int[n + 1];
    return integerBreakHelper(n);
}
public int integerBreakHelper(int n) {
    if (n == 2) {
        return 1;
    }
    // memory的初始值为0,如果它不为0,说明已经计算过了,直接返回即可
    if (memory[n] != 0) {
        return memory[n];
    }
    int res = -1;
    for (int i = 1; i <= n - 2; i++) {
        res = Math.max(res, Math.max(i * integerBreakHelper(n - i), i * (n - i)));
    }
    // 将每次计算的结果保存到备忘录数组中
    memory[n] = res;
    return res;
}
}

动态规划

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

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值