Loading

[算法笔记]leetcode 343 整数拆分

leetcode 343 整数拆分

题目描述

给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回你可以获得的最大乘积 。

示例 1:

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

示例 2:

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

提示:

  • 2 <= n <= 58

思路推导

先试几个数

num
1 1 + 0 0 不能拆
2 1 +1 1
3 1 + 2 2 2可以拆
2 + 1 2 2可以拆
1 + 1 + 1 1 1不能拆
4 1 +3 3 3 可以拆
2 + 2 4 2 可以拆
3 + 1 3 1不能拆
1 + 1 + 2 2 2可以拆
1 + 2 + 1 2 2可以拆
2 + 1 + 1 2 2可以拆
1 + 1+ 1+1 1 1不能拆

分析:

以 num = 4 为例子,可以拆成 1,3。
i. 拆成两个数字:直接相乘,乘积为3,
ii. 拆成n个数字(n>=3), 其中3 可以进行拆分 。要明确拆的目的是要求 1*[...] 的最大值,也就是求 3 拆成的相加序列[....] 的乘积的最大值。 可以看出 求3拆分的最大值是 其子问题。

确定dp[], dp[i] 为数字 i 拆分后乘积最大的数值,i 为数字i

也就是说:情况1: 两数相乘;情况2:多数相乘 中选值最大的。
$dp[i] = max{{i(i-j),j*dp[i-j],dp[i]}}$

注:max 中有dp[i],是由于内循环中 j 的每次变化会更新一次dp[i],要保证遍历完 j 后 dp[i] 中的数字为最大值。

代码

#include<bits/stdc++.h>  
using namespace std;  
  
class Solution {  
private:  
    int get_max(int num1,int num2,int num3){  
        int tm1 = max(num1,num2);  
        int tm2 = max(num2,num3);  
        return max(tm1,tm2);  
            }  
public:  
    int integerBreak(int n) {  
        vector<int> dp(n+1,0);  
        for(int i = 2;i<=n;i++){  
            for(int j = 1;j<i;j++){  
                dp[i] = get_max(j*dp[i-j],j*(i-j),dp[i]);  
//                cout<<i<<" "<<j<<endl;  
            }            }            return dp[n];  
    }  
};

贪心的做法

$3m +k$ : m 个三 加剩余的数字
$3^{m}
k$: 相乘

posted @ 2026-03-08 19:57  GIPV  阅读(0)  评论(0)    收藏  举报