算法力扣刷题记录 八十一【343. 整数拆分】

前言

动态规划第8篇。记录 八十一【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

二、尝试实现

分析题目,确定方法

  1. 题目给了一个正整数n,拆分成k个正整数,使得k个正整数乘积最大。但是没有说k能是几。感觉是一种尝试的过程,好像没有方法。
  2. 思考:a + b = 常数;当a=b时,a * b 最大。这个结论在初高中都学过:当几个数的和固定,那么这几个数相等时乘积最大。所以:当n拆分成近似相等的k个数,乘积才会最大
  3. 有了结论后,思考能拆成几个数呢?也就是k如何确定?比如n=11:
    在这里插入图片描述
  4. 所以思路不正确。

三、参考学习

【343. 整数拆分】 参考学习链接

3.1动态规划思路

  1. 原理:分成两个因子,固定一个j,可以继续对n-j拆分。有了固定,就方便遍历。
  2. 同时可以发现下图中:两个因子在n/2之后重复,颠倒顺序而已。所以,遍历到n/2即可结束。
    在这里插入图片描述
  3. dp数组含义和下标含义:一维数组dp[i]。当n=i时,拆分因子后的最大乘积值是dp[i]。
  4. 递推公式:
  • 当拆成两个因子:j * (i-j)
  • 当拆成三个及以上的因子:固定j,继续对i-j拆分。那么i-j拆分后的最大乘积是dp[i-j]。所以此时乘积为j * dp[i-j]
  • 选择最大的:max(j * (i-j) , j * dp[i-j])。
  • dp[i] = max(j * (i-j) , j * dp[i-j] , dp[i]);为什么有dp[i]?因为j是不断遍历的,dp[i]暂时存放某一个j得出的最大乘积。所以加上dp[i]后比较。
  1. 初始化:
  • dp[0]没有含义,dp[0] = 0作为因子乘以 j 后依然是0。不影响结果。
  • dp[1]没有含义,dp[1] = 0作为因子乘以 j 后依然是0。不影响结果。
  • dp[2] = 1.
  1. 遍历顺序:递推公式dp[i]用到dp[i-j]在dp[i]的前面,所以遍历从前往后。

3.2代码实现【动态规划】

class Solution {
public:
    int integerBreak(int n) {
        //定义dp数组
       vector<int> dp(n+1,0);
        //初始化
        dp[2] = 1;

        //遍历顺序
        for(int i = 3;i < n+1;i++){//总和为i
            for(int j = 1;j <= i/2;j++){//拆分两个因子
                dp[i] = max(max(j * (i-j), j * dp[i-j]),dp[i]);
            }
        }
        return dp[n];
    }
};

3.3贪心算法思路

  1. 应用结论:把n拆成多个3,直到无法再拆成3,最后如果是4,则保留4作为最后一个因子。这样得到的乘积最大。
  2. 2是质数,3是质数,没有别的加数,拆到因子包含多个3这一步,对于3无法再继续拆。那么将n尽可能的拆成多个3,最后保留小于等于4的因子,因子之间近似相等,并且无法拆分。
  3. 为什么不是到质数5停止?因为5 = 2+3,还有两个加数。(不是严格证明,可以这样辅助理解下)
    在这里插入图片描述

3.4 代码实现【贪心:尽可能的拆分多个3】

class Solution {
public:
    int integerBreak(int n) {
        if(n == 2) return 1;
        if(n == 3) return 2;
        if(n ==4) return 4;

        int result = 1;
        while(n > 4){
            result *= 3;
            n -= 3;
        }
        result *= n;
        return result;
    }
};

总结

本题需要掌握正确思路,获取方法。贪心给出一种说法可以解释原因,非严格数学证明。
在这里插入图片描述
(欢迎指正,转载标明出处)

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值