【Leetcode】NO.343 整数的拆分 (C++&Python) [动态规划]

题目:整数的拆分

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

思路

  • 动态规划题
  1. 对于i对应的是i的最大乘积,索引从1开始dp数组开n+1;
  2. 对于j对应的是拆分数,索引从1开始,最大到i-1(最后是n-1);
  3. 每个位置的最大值是对于拆分j*dp[i-j], 和 直接拆j *(i-j),选择最大;
  4. 最后直接返回dp[n]

在看题解的时候看到了使用数学的方法进行coding,很灵活;
大概意思是拆分的是尽可能拆分成3:
这是因为例如:
5,6这些大于3的,如果不拆分则为本身;
拆分的话(5=2+3<2*3),6=2+2+2=3+3 ==>(2*2*2 < 3*3),只要是大于4的数直接拆分成3,直到不能继续拆分为止;(ps:这里的6继续拆分之后数值比原来要打,之后就是比较拆分中哪种最大,很明显拆分成3的要比其他大)
说明拆分成2要小于拆分成3的,这是利用数学证明的;

代码

Python 版本

class Solution:
    def integerBreak(self, n: int) -> int:
        # dp 求解
        dp = [0]*(n+1)
        dp[2] = 1
        for i in range(3,n+1): # 0不用
            for j in range(1,i-1): # 从1开始拆分, {1,1....} 最大拆到n-1,用i来表示是i-1,右边是取不到的,但是i是重索引1开始当i是能够索引到n 的,所以i-1索引到n-1
                dp[i] = max(dp[i], dp[i-j]*j, (i-j)*j)
        return dp[n]

C++ 版本


class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n+1,0);
        dp[2] = 1;
        for(int i=3;i<dp.size();i++)
        {
            for(int j=1;j<i-1;j++)
            {
                dp[i] = max(dp[i],max(dp[i-j]*j, (i-j)*j));
            }
        }

        return dp[n];
    }
};

运行结果图

image

posted @ 2022-01-02 23:08  jucw  阅读(152)  评论(0编辑  收藏  举报