leetcode
leetcode 601 ~ 650
24 点游戏

24 点游戏

难度:

标签:

题目描述

代码结果

运行时间: 36 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用stream处理卡片的排列和运算符组合。
 * 2. 通过递归计算可能的表达式值。
 */
import java.util.*;
import java.util.stream.Collectors;
 
public class SolutionStream {
    public boolean judgePoint24(int[] cards) {
        return permute(Arrays.stream(cards).boxed().collect(Collectors.toList()));
    }
 
    private boolean permute(List<Double> nums) {
        if (nums.size() == 1) return Math.abs(nums.get(0) - 24) < 1e-6;
        return nums.stream()
                .flatMap(a -> nums.stream().filter(b -> !b.equals(a)).map(b -> Arrays.asList(a, b)))
                .map(pair -> compute(pair.get(0), pair.get(1)))
                .flatMap(Collection::stream)
                .anyMatch(result -> {
                    List<Double> next = nums.stream()
                            .filter(n -> !n.equals(pair.get(0)) && !n.equals(pair.get(1)))
                            .collect(Collectors.toList());
                    next.add(result);
                    return permute(next);
                });
    }
 
    private List<Double> compute(double a, double b) {
        return Arrays.asList(a + b, a - b, b - a, a * b, b != 0 ? a / b : null, a != 0 ? b / a : null)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
}
 

解释

方法:

此题解采用了递归回溯的方法来解决24点游戏。主要思路是,每次递归中选择两个数字进行所有四种运算(加、减、乘、除),并将结果作为新的数字与剩余的数字一起继续递归处理,直到数组中只剩下一个数字,如果这个数字接近24(由于浮点运算,这里使用了一个小的阈值来判断),则返回true。对于除法和减法,由于它们不满足交换律,需要额外处理两个数字位置交换的情况。递归终止的基本情况是当数组中只剩一个数字,检查这个数字是否接近24。

时间复杂度:

O(1) (因为输入的卡片数量固定为4,所以时间复杂度可以视为常量时间复杂度)

空间复杂度:

O(4) (递归深度)

代码细节讲解

🦆
为什么选择使用递归回溯方法来解决这道24点游戏题目?
递归回溯方法适用于这种问题因为24点游戏要求我们探索所有可能的数字组合和运算符组合,以找到能够形成特定值(如24)的表达式。递归允许我们深入每一种可能的运算和数字组合,而回溯则允许我们在一条路径不再有希望时放弃它,回退到上一步尝试其他可能的路径。这种方法在解决需要枚举多种组合和顺序的问题时非常高效。
🦆
递归方法中,如何处理数字的重复使用问题,避免在递归过程中多次选择同一数字?
在递归中处理重复数字的问题,通过在每次递归调用时创建一个新的数字列表来解决。在具体实现中,我们首先选择两个数字进行运算,然后将这两个数字从当前列表中移除,将运算结果添加到剩余数字的列表中。通过索引确保每次只选择不同的数字。这样,即使原始数组中有重复的数字,也能保证每次递归处理的是不同的数字实例,从而避免了在递归过程中多次使用同一数字的问题。
🦆
在递归过程中,你是如何决定在哪一层递归中终止并返回结果的?
在递归过程中,终止条件是当数字列表只剩一个数字时。在每次递归中,我们通过不同的运算减少列表中的数字数量,直到列表中仅剩一个数字。如果这个数字非常接近24(由于浮点数的精度问题,通常使用一个小的阈值如1e-6来判断),我们认为找到了一个有效的解决方案,返回true。如果所有的路径都被尝试过后没有找到解决方案,最终返回false。这种方法确保了我们能够全面地探索所有可能的数字和运算符组合,直到找到答案或确认无解。

相关问题