343. Integer Break

探讨将正整数拆分成至少两个正整数之和,并最大化这些整数乘积的问题。通过分析数学规律,提出O(n)的高效算法解决方案,避免了传统DP方法的高时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

Example 1:

Input: 2
Output: 1
Explanation: 2 = 1 + 1, 1 × 1 = 1.

Example 2:

Input: 10
Output: 36
Explanation: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36.

分析:

这道题标注在DP下但是貌似用简单的DP时间复杂度太高了。。O(n2)

D[i] = max(i, max(D[a],a)*max(D[b],b)) (其中a+b=i)

看了题目的提示应该有O(n)的解法,所以需要利用一点数学规律(分结成2/3,且越多3越好),证明就不说了,转移公式改为:

dp[i] = max(2 * dp[i - 2], 3 * dp[i - 3])

public static int integerBreak2(int n) {
    if(n <= 3) return n - 1;
    int[] dp = new int[n + 1];
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 3;
    for(int i = 4; i <= n; ++i)
    {
        dp[i] = Math.max(2 * dp[i - 2], 3 * dp[i - 3]);
    }
    return dp[n];
}

上面这个思路转化下,其实就是能分解为3,就尽可能分解为3,

分为下面几种情况:

n % 3 == 0  就全部分解为3。

n % 3 == 1 肯定有个4,剩下的分解为3。(4分结成2*2比1*3大)

n % 3 == 2 有个2,剩下的全部分解为3。

 public int integerBreak(int n) {
        if(n<=3)
            return n-1;//n<=3不符合规律
        else if(n%3==0)
            return (int)Math.pow(3,n/3);//注意如果不强制转换会抛异常
        else if(n%3==1)
            return (int)Math.pow(3,(n-4)/3)*4;
        else
            return (int)Math.pow(3,(n-2)/3)*2;
    }

 

### 解决 `java.lang.Integer cannot be cast to java.lang.Long` 类型转换错误 在方法 `public List<ModelVo1> selectTypeList(String modelId)` 中,出现 `java.lang.Integer cannot be cast to java.lang.Long` 错误的原因在于代码尝试将 `Integer` 类型的值强制转换为 `Long` 类型。Java 中,`Integer` 和 `Long` 是不同的包装类,不能直接进行类型转换[^1]。 #### 问题分析 错误发生在以下代码段中: ```java if (Integer.valueOf(con.get("type_id").toString()) == m.getTypeId()) { m.setConfigurationId(Long.valueOf(con.get("configuration_id").toString())); } ``` 这里的问题是 `con.get("type_id")` 返回的是一个 `Long` 类型的对象,而 `m.getTypeId()` 返回的是 `Integer` 类型。由于 `Integer` 和 `Long` 是不同的包装类,直接比较或转换会导致运行时异常。 #### 解决方案 可以通过以下方式解决该问题: 1. **统一数据类型**:确保所有涉及的字段类型一致。例如,如果数据库中的 `type_id` 和 `configuration_id` 都是 `BIGINT` 类型,则应将 Java 中对应的字段类型设置为 `Long`。 2. **显式类型转换**:在需要比较或赋值时,显式地将 `Integer` 转换为 `Long` 或反之。 以下是优化后的代码示例: ```java public List<ModelVo1> selectTypeList(String modelId) { List<HashMap<String, Long>> configuration = modelMapper.getConfiguration(modelId); List<ModelVo> modelVos = modelMapper.selectTypeList(modelId); List<ModelVo1> vo1s = new ArrayList<>(); for (ModelVo modelVo : modelVos) { ModelVo1 m = new ModelVo1(); m.setModelId(modelVo.getModelId()); m.setTypeId(modelVo.getTypeId()); m.setTypeName(modelVo.getTypeName()); // 将 Integer 转换为 Long 进行比较 Long typeIdAsLong = ((Long) modelVo.getTypeId()).longValue(); for (HashMap<String, Long> con : configuration) { if (con.get("type_id").equals(typeIdAsLong)) { m.setConfigurationId(con.get("configuration_id")); break; } } vo1s.add(m); } return vo1s; } ``` #### 优化点说明 1. **类型一致性**:通过将 `modelVo.getTypeId()` 转换为 `Long` 类型,避免了 `Integer` 和 `Long` 的不兼容问题[^2]。 2. **减少嵌套逻辑**:移除了不必要的注释代码和重复逻辑,使代码更加简洁易读。 3. **性能改进**:通过 `break` 提前终止内层循环,减少了不必要的迭代次数。 #### 数据库配置映射优化 为了进一步优化 `type_id` 和 `configuration_id` 的映射关系,可以使用 `Map<Long, Long>` 来存储配置信息,从而避免嵌套循环。例如: ```java public List<ModelVo1> selectTypeList(String modelId) { List<HashMap<String, Long>> configuration = modelMapper.getConfiguration(modelId); Map<Long, Long> configMap = new HashMap<>(); for (HashMap<String, Long> con : configuration) { configMap.put(con.get("type_id"), con.get("configuration_id")); } List<ModelVo> modelVos = modelMapper.selectTypeList(modelId); List<ModelVo1> vo1s = new ArrayList<>(); for (ModelVo modelVo : modelVos) { ModelVo1 m = new ModelVo1(); m.setModelId(modelVo.getModelId()); m.setTypeId(modelVo.getTypeId()); m.setTypeName(modelVo.getTypeName()); Long typeIdAsLong = ((Long) modelVo.getTypeId()).longValue(); if (configMap.containsKey(typeIdAsLong)) { m.setConfigurationId(configMap.get(typeIdAsLong)); } vo1s.add(m); } return vo1s; } ``` #### 优化点说明 1. **使用 `Map` 提高查找效率**:通过将 `configuration` 数据存储在 `Map` 中,避免了嵌套循环,将时间复杂度从 O(n*m) 降低到 O(n+m)[^3]。 2. **代码可读性提升**:逻辑更加清晰,便于维护和扩展。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值