343、整数拆分

  1. 343、整数拆分
    1. 示例 1:
    2. 示例 2:
  • 题解
    1. 1、暴力深度优先搜索
    2. 2、记忆化深度优先搜索
    3. 3、动态规划
    4. 4、数学公式,有证明
  • 343、整数拆分

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

    示例 1:

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

    示例 2:

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

    说明: 你可以假设 n 不小于 2 且不大于 58。

    题解

    1、暴力深度优先搜索

    $F(n) = \max(i*F(n-i)),i = 1,2,3…n-1$

    • 代码
    // java
    class Solution {
        public int integerbreak(int n) {
            // 递归结果
            if (n == 2) {
                return 1;
            }
            int res = -1;
            // 迭代求最大值
            for (int i = 1;i < n;i++) {
                res = Math.max(res, Math.max(i*(n-i),i*integerBreak(n-i)));
            }
            return res;
        }
    }
    

    2、记忆化深度优先搜索

    • 又称为自顶而上的动态规划
    • 代码
    // java
    class Solution {
        // 记忆的辅助数组
        int[] memo;
        public int integerBreak(int n) {
            memo = new int[n+1];
            return integerBreakCore(n);
        }
    
        private int integerBreakCore(int n) {
            if (n == 2) {
                return 1;
            }
            // 记忆数组检查(剪枝检查)
            if (memo[n] != 0) return memo[n];
            int res = -1;
            for (int i = 1;i < n;i++) {
                res = Math.max(res, Math.max(i*(n-i),i*integerBreakCore(n - i)));
            }
            memo[n] = res; 
            return memo[n];
        }
    }
    

    3、动态规划

    • 自下而上的递推公式
      • dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]))
    // java
    class Solution {
        public int integerBreak(int n) {
            int[] dp = new int[n + 1];
            dp[2] = 1;
            // i= 3...n, 求出dp[i]
            for (int i = 3;i <= n;i++) {
                // 求最优的加数乘积
                for (int j = 1;j < i;j++) {
                    dp[i] = Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
                }
            }
            return dp[n];
        }
    }
    

    4、数学公式,有证明

    • 将数字nn拆分为尽量多的3,可以保证乘积最大。下面简单分类讨论:
      • 若$n \equiv 0(mod \ 3)n≡0(mod 3)$,即n=3k,则拆分为k个3
      • 若$n \equiv 1(mod \ 3)n≡1(mod 3)$,即$n=3k+1=3(k-1)+2\times 2n=3k+1=3(k−1)+2×2$,则拆分为k-1个3,2个2
      • 若$n \equiv 2(mod \ 3)n≡2(mod 3)$,即$n=3k+2n=3k+2$,则拆分为k个3,1个2
    • 考虑到边界情况,当n \le 3n≤3时无法拆分,故直接讨论:
      • n=2,只有2=1+1,此时最大值为1
      • n=3,只有3=1+2,此时最大值为2
      • 以上两种情形可以合并为:当$n \le 3$时,最大值为n-1
        综上所述:

    $$ F(n)=\left{
    \begin{array}{rcl}
    n - 1 & & {n \le 3}\
    13^k & & {n = 3k(k \ge 2)}\
    4
    3^{k - 1} & & {n = 3k+1 (k \ge 1)}\
    2*3^{k - 1} & & {n = 3k+2 (k \ge 1)}
    \end{array} \right.
    $$

    作者:amanehayashi
    链接:https://leetcode-cn.com/problems/integer-break/solution/zheng-shu-chai-fen-shu-xue-fang-fa-han-wan-zheng-t/

    • 代码
    public class solution{
        public int integerBreak(int n) {
            // p有三种值:0,1,2, q>=0, r有三种值:1 4 2
            int p = n%3,q = n/3, r = p + (2*p+1) % 5;
            // 巧妙的计算分段函数
            return n <= 3 ? n - 1:(int)(Math.pow(3, q - (p & 1)) * r);
        }
    }
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:343、整数拆分

    Count:752

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/343%E3%80%81%E6%95%B4%E6%95%B0%E6%8B%86%E5%88%86/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation