343. 整数拆分

196 阅读1分钟

[343. 整数拆分]

「这是我参与2022首次更文挑战的第35天,活动详情查看:2022首次更文挑战」。

题目描述

给定一个正整数 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

思路

这是一道 动态规划 的题。判定一道题使用动态规划的标准是看当前状态是否依赖之前的状态,即问题由许多重复的子问题组成,一个数可以看成多个数字相乘而成,在进行下一个数时,可以借助之前的拆分结果。这道题的子问题判定为是之后有以下几个步骤:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

具体到这道题:

1、dp数组含义:拆分和为i的最大乘积为dp[i]。

2、递推公式:可以将i拆分为两数:j和i-j,乘积为j*(i-j),也可以在拆出j后,对i-j再进行拆分,那么乘积就是j*dp[i-j] 其中的dp[i-j]即为拆分和为i-j的最大乘积,通过不断的尝试拆j,取最大值,即dp[i]=max(j*(i-j),j*dp[i-j]) ;

3 、初始化:按照题目的意思,i<2时。不需要初始化,那么需要初始化第一个值dp[2]=1。

4、遍历顺序:依赖之前的状态,即从前往后遍历。

5、 0,0,1,2,4,6....(dp[0],dp[1]无意义)

代码实现

细节见注释

class Solution {
public:
    int integerBreak(int n) {
    vector<int> dp(n+1);
    dp[2]=1;     //初始化
    for(int i=3;i<=n;++i){     //从3开始
        for(int j=1;j<i-1;++j){         //从1开始拆,拆至i-j==2,因为i-j<2时,i-j不可拆
            dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));  //递推公式
        }
    }
    return dp[n];
    }
};

总结

简要的介绍了动态规划,动态规划的一般做题步骤等等。