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

如何不使用组合数组实现24点判断算法?

不用组合数组实现24点判断的优雅方案

嘿,我懂你为啥不想用那个硬编码的全排列数组来做24点判断了——手动枚举所有排列和运算表达式不仅容易漏情况,代码还特别臃肿。其实咱们可以用递归分治的思路来实现,完全不需要预定义任何组合数组,还能更全面地覆盖所有可能的运算和括号场景。

核心思路:递归分治拆解问题

24点的本质是通过任意组合数字顺序、运算符号和括号,让最终结果等于24。递归分治的思路就是把这个问题逐步拆解:

  • 从4个数开始,每次选两个数进行所有可能的运算(加、减、乘、除,注意减法和除法有顺序区别);
  • 把运算结果和剩下的数合并成新的数字列表,把问题转化为「用3个数凑24」;
  • 重复这个过程,直到列表只剩1个数,判断它是否接近24(因为除法会产生浮点数,要考虑精度误差)。

这个方法自动覆盖了所有数字排列和括号优先级的情况——不同的数对选择顺序,就等价于不同的括号组合。

完整Java实现代码

import java.util.ArrayList;
import java.util.List;

public class TwentyFourGameSolver {
    private static final double TARGET = 24;
    private static final double EPSILON = 1e-6; // 处理浮点数精度误差,避免因计算精度误判

    public static boolean canBeEqualTo24(int[] nums) {
        // 输入合法性校验
        if (nums.length != 4) return false;
        for (int num : nums) {
            if (num < 1 || num > 9) return false;
        }

        // 将int数组转为double列表,方便处理除法运算
        List<Double> numList = new ArrayList<>();
        for (int num : nums) {
            numList.add((double) num);
        }

        return solve(numList);
    }

    private static boolean solve(List<Double> nums) {
        int size = nums.size();
        // 递归终止条件:只剩一个数,判断是否接近目标值24
        if (size == 1) {
            return Math.abs(nums.get(0) - TARGET) < EPSILON;
        }

        // 枚举所有可能的两个数组合
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                if (i == j) continue; // 跳过同一个数的情况

                // 收集除了选中的两个数之外的剩余数字
                List<Double> nextNums = new ArrayList<>();
                for (int k = 0; k < size; k++) {
                    if (k != i && k != j) {
                        nextNums.add(nums.get(k));
                    }
                }

                double a = nums.get(i);
                double b = nums.get(j);

                // 加法:a+b(和b+a结果一致,只需要计算一次)
                nextNums.add(a + b);
                if (solve(nextNums)) return true;
                nextNums.remove(nextNums.size() - 1); // 回溯,尝试下一种运算

                // 减法:a - b
                nextNums.add(a - b);
                if (solve(nextNums)) return true;
                nextNums.remove(nextNums.size() - 1);

                // 减法:b - a(顺序不同结果不同,需要单独计算)
                nextNums.add(b - a);
                if (solve(nextNums)) return true;
                nextNums.remove(nextNums.size() - 1);

                // 乘法:a*b(和b*a结果一致,只需要计算一次)
                nextNums.add(a * b);
                if (solve(nextNums)) return true;
                nextNums.remove(nextNums.size() - 1);

                // 除法:a / b,除数不能为0
                if (Math.abs(b) > EPSILON) {
                    nextNums.add(a / b);
                    if (solve(nextNums)) return true;
                    nextNums.remove(nextNums.size() - 1);
                }

                // 除法:b / a,除数不能为0(顺序不同结果不同,需要单独计算)
                if (Math.abs(a) > EPSILON) {
                    nextNums.add(b / a);
                    if (solve(nextNums)) return true;
                    nextNums.remove(nextNums.size() - 1);
                }
            }
        }

        // 所有可能的运算组合都尝试过,无法得到24
        return false;
    }

    // 测试示例
    public static void main(String[] args) {
        System.out.println(canBeEqualTo24(new int[]{4, 1, 8, 7})); // 输出true,对应(8-4)*(7-1)=24
        System.out.println(canBeEqualTo24(new int[]{3, 3, 8, 8})); // 输出true,对应8/(3-8/3)=24
        System.out.println(canBeEqualTo24(new int[]{1, 2, 3, 4})); // 输出true,对应1*2*3*4=24
        System.out.println(canBeEqualTo24(new int[]{1, 1, 1, 1})); // 输出false
    }
}

这个方案的优势

  1. 无需组合数组:递归过程自动遍历了所有数字的排列和运算顺序,完全不需要手动定义全排列数组;
  2. 覆盖所有场景:支持非整除的除法运算,能处理像[3,3,8,8]这种经典的24点问题(原代码会因为只支持整除而漏判);
  3. 扩展性强:如果以后要支持更多数字(比如5个数凑某个目标值),只需要修改输入校验部分,核心递归逻辑无需改动;
  4. 代码更简洁:避免了原代码中大量重复的条件判断,可读性和维护性更高。

原代码的局限性

原代码通过手动枚举部分排列和运算表达式,很容易遗漏大量可能的解,比如嵌套括号的运算、非整除的除法等,会导致很多本应返回true的情况被误判为false。递归分治的方法则能彻底解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:18:11