You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归实现mySplit函数:整数数组分组判断需求与优化问询

另一种递归实现mySplit的思路

嘿,我来给你分享一个更清晰的递归实现思路,完全贴合你提出的四个规则,而且把核心逻辑都放在递归辅助函数里,mySplit只做前置处理和返回结果~

先理清楚问题的核心转化

首先我们可以把数组里的元素分成三类,提前处理规则3和规则4:

  • 5的倍数:必须全部在同一组(我们默认放到第一组,不影响结果,因为只要两组总和相等就行),先计算它们的总和sum5
  • 3的倍数(非5的倍数):必须全部在第二组,计算它们的总和sum3
  • 自由数:既不是3也不是5的倍数的数,这些可以自由分配到两组中的任意一组,我们把它们收集到列表里,计算总和sumFree

接下来推导两组总和相等的条件:
设第一组的总和 = sum5 + x(x是自由数中分到第一组的和)
第二组的总和 = sum3 + (sumFree - x)
要让两组相等,必须满足:
sum5 + x = sum3 + sumFree - x
整理后得到:
2x = sum3 + sumFree - sum5
这意味着:

  1. sum3 + sumFree - sum5必须是非负偶数,否则x不是非负整数,不可能实现
  2. 我们需要从自由数中选出一个子集,使得它们的和等于(sum3 + sumFree - sum5) / 2——这就是递归要解决的子集和问题!

具体代码实现

public class SplitArray {
    public static boolean mySplit(int[] nums) {
        int sum5 = 0;
        int sum3 = 0;
        int sumFree = 0;
        // 收集自由数的列表,方便后续递归处理
        java.util.List<Integer> freeList = new java.util.ArrayList<>();
        
        for (int num : nums) {
            if (num % 5 == 0) {
                sum5 += num;
            } else if (num % 3 == 0) {
                sum3 += num;
            } else {
                freeList.add(num);
                sumFree += num;
            }
        }
        
        // 计算目标值:需要从自由数中凑出的和
        int target = sum3 + sumFree - sum5;
        // 目标必须是非负偶数,否则直接返回false
        if (target < 0 || target % 2 != 0) {
            return false;
        }
        target /= 2;
        
        // 调用递归辅助函数,判断是否能凑出目标和
        return canReachTarget(freeList, 0, 0, target);
    }
    
    // 递归辅助函数:判断从index开始的自由数能否凑出target
    // 参数:自由数列表、当前处理的索引、当前累加的和、目标和
    private static boolean canReachTarget(java.util.List<Integer> freeList, int index, int currentSum, int target) {
        // 终止条件1:当前和等于目标,找到可行方案
        if (currentSum == target) {
            return true;
        }
        // 终止条件2:遍历完所有数还没凑到目标,返回false
        if (index >= freeList.size()) {
            return false;
        }
        
        // 递归两种选择:选当前数,或者不选当前数
        int currentNum = freeList.get(index);
        // 选当前数:当前和加上这个数,索引+1
        boolean choose = canReachTarget(freeList, index + 1, currentSum + currentNum, target);
        // 不选当前数:当前和不变,索引+1
        boolean notChoose = canReachTarget(freeList, index + 1, currentSum, target);
        
        // 只要其中一种选择可行,就返回true
        return choose || notChoose;
    }
    
    // 测试示例
    public static void main(String[] args) {
        System.out.println(mySplit(new int[]{1, 1})); // true
        System.out.println(mySplit(new int[]{1, 1, 1})); // false
        System.out.println(mySplit(new int[]{2, 4, 2})); // true
        System.out.println(mySplit(new int[]{5, 21, 8, 15, 7})); // true
        System.out.println(mySplit(new int[]{15, 10, 5})); // false
        System.out.println(mySplit(new int[]{15, 8, 7})); // true
    }
}

思路解释

  1. 前置处理:把数组元素按规则分类,提前计算固定组的总和,把可变部分提取出来,简化递归的问题规模
  2. 递归逻辑:对于每个自由数,我们有两种决策——加入第一组或者不加入,递归遍历所有可能的组合,只要找到一种组合能凑出目标和,就返回true
  3. 终止条件:要么找到符合条件的组合,要么遍历完所有数都找不到,终止递归

这种思路把复杂的分组问题转化为经典的子集和递归问题,逻辑清晰,也完全符合你要求的“所有逻辑在递归函数中实现,mySplit仅返回布尔值”的要求。

内容的提问来源于stack exchange,提问作者simon francis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:00:23