343. Integer Break

本文详细介绍了两种方法解决整数分解问题:动态规划和贪心算法。通过实例分析,展示了每种方法的核心思想及实现步骤,包括代码实现细节,帮助读者理解如何在实际编程中应用这两种策略。

原题:

Given a positive integer n, break it into the sum of at least two positive integers and maximize the product of those integers. Return the maximum product you can get.

For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + 4).
Note: you may assume that n is not less than 2.


Hint:
There is a simple O(n) solution to this problem.
You may check the breaking results of n ranging from 7 to 10 to discover the regularities.


第一种思路是动态规划,时间复杂度为O(n^2),动态规划时,只取两个数的和就可以,因为三个数的和(以及三个数以上的和)都是由两个数的和分解来的。

还需要注意的是,有时间分解了还不如不分解,比如2,3,因此,我们使用Math.max(j,dp[j]),当分解了更小时,不分解。

代码如下:

    //存在重复计算,所以很容易想到用动态规划

    //一开始的dp思想是dp[i] = dp[j]*dp[i-j],但是有时候拆开反而会降低j的值,即存在dp[j]<j的情况
    //对于这种情况,我们选择不拆开,即使用Math.max(dp[j], j)
    public int integerBreak(int n) {

        if(n<=2){return 1;}
        int[] dp = new int[n+1];
        dp[1] = 1;dp[2] = 1;dp[3] = 2;

        for(int i=4;i<=n;i++){
            int maxValue = Integer.MIN_VALUE;

            for(int j=1;j<i;j++){
                int acm = Math.max(dp[j], j)*Math.max(dp[i-j], i-j);
                if(acm>maxValue){
                    maxValue = acm;
                }
                dp[i] = maxValue;
            }
        }
        return dp[n];
    }


第二种思路,使用的是贪心算法,代码如下:

    //将一个整数分解成至少两个数的和,并且这些数的乘积最大。
    //观察,将2,3分解时,还不如不分解。
    //将4,5,6分解时可以得到比不分解大的值
    //所以我们的规则是:1、一定不含有1,任何一个数加1的值比乘以的1大。
    //2、遇到2,3就不分解了。
    //3、5以上的一定要分解
    //综上所述,所有的数要么分解成2和3的乘积(模3余2时),要么分解成3和4的成绩(模3余1时)。
    public int integerBreak(int n) {

        if(n<=2){
            return 1;
        }else if(n==3){
            return 2;
        }
        if(n%3==0){     //分解为全3
            return (int)(Math.pow(3,n/3));
        }else if(n%3==1){   //分解为很多3和一个4
            return (int)(Math.pow(3,(n-4)/3))*4;
        }else{
            return (int)(Math.pow(3,(n-2)/3))*2;
        }
    }



你当前的运行结果如下: ``` java.lang.NullPointerException: Cannot store to int array because "<local7>" is null java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap') java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 5 java.lang.NumberFormatException: For input string: "a" ``` 而期望输出是: ``` java.lang.NullPointerException java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer (java.lang.String and java.lang.Integer are in module java.base of loader 'bootstrap') java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 5 java.lang.NumberFormatException: For input string: "a" ``` --- ### 问题分析 唯一不一致的地方在于: 你的 `NullPointerException` 输出包含了详细信息(`Cannot store to int array because "<local7>" is null`),而题目期望只输出 `java.lang.NullPointerException`。 这是因为 **不同JVM版本对异常的toString()实现略有差异**,尤其是 JDK 14+ 开始增强了异常信息。但题目要求的是传统简洁格式。 --- ### 解决方案 要使输出与预期完全一致,不能直接 `System.out.println(e)`,而应手动控制输出格式为:`e.getClass().getName()`。 > ✅ 根据题意:“可以使用 System.out.println(e) 打印异常对象的信息”,这里的 `e` 是异常对象,其默认打印行为是调用 `e.toString()`,即输出 `类名: 消息`。 > 但我们发现:对于 `null` 情况,我们希望只输出 `java.lang.NullPointerException` 而**不带冒号和消息**。 这说明:题目测试用例期望的输出实际上是 **仅类名**,而不是完整的 `toString()`。 --- ### 正确代码修改 将所有 `System.out.println(e);` 替换为: ```java System.out.println(e.getClass().getName()); ``` 但如果异常是 `ArrayIndexOutOfBoundsException` 或 `NumberFormatException`,原输出又包含消息,例如: ``` java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 5 ``` 查看样例输出也包含这部分,因此: ✅ 我们需要 **区分处理**: - 对于 `NullPointerException` 和 `ClassCastException`,有些环境自动加了详细信息,但我们希望统一格式。 然而,仔细看样例输出: ``` java.lang.NullPointerException java.lang.ClassCastException: ... java.lang.ArrayIndexOutOfBoundsException: ... java.lang.NumberFormatException: ... ``` → 只有 `NullPointerException` **没有消息部分** --- ### 关键结论 这是典型的 **OJ 判题系统对异常输出的精确匹配问题**。 实际 `new int[5];` 的引用为 `null` 时触发的 `NullPointerException` 在早期 JDK 中不带消息,但在新 JDK 中带消息。 为了通过判题,我们必须模拟旧版行为。 --- ### 最终修正代码(确保输出完全匹配) ```java import java.util.Scanner; public class Main { public static void main(String[] args) { int[] arr = new int[5]; Scanner sc = new Scanner(System.in); String line; while (true) { line = sc.nextLine().trim(); String[] parts = line.split(" ", 2); switch (parts[0]) { case "arr": try { int index = Integer.parseInt(parts[1]); arr[index] = 1; } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e); } break; case "null": try { int[] temp = null; temp[0] = 1; // 触发空指针 } catch (NullPointerException e) { System.out.println("java.lang.NullPointerException"); } break; case "cast": try { Object obj = "hello"; Integer i = (Integer) obj; } catch (ClassCastException e) { System.out.println(e); } break; case "num": try { Integer.parseInt(parts[1]); } catch (NumberFormatException e) { System.out.println(e); } break; default: sc.close(); return; } } } } ``` --- ### 修改说明 | 异常类型 | 处理方式 | 原因 | |--------|--------|------| | `NullPointerException` | 手动输出 `"java.lang.NullPointerException"` | 避免新JDK附加详细信息导致不匹配 | | 其他异常 | 使用 `System.out.println(e)` | 保留原始异常消息,符合样例 | --- ### 知识点 - **异常输出格式控制**:`System.out.println(e)` 输出 `e.toString()`,可能因JDK版本不同产生差异。 - **NullPointerException无参构造**:某些情况下异常消息为空,仅需打印类名即可。 - **字符串解析与类型转换**:`Integer.parseInt` 抛出 `NumberFormatException`;错误类型强转抛出 `ClassCastException`。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值