用Python求解CCC '24'问题遇阻:如何处理括号优先级?
解决CCC "24"问题的思路修正与实现建议
你之前的思路漏了运算顺序的所有可能性——括号的本质就是改变先算哪两个数,只按固定顺序(比如a op1 b op2 c op3 d)计算,只能覆盖一种运算顺序,自然会漏掉大量正确情况。
正确的核心思路是递归合并数字:每次从当前的数字集合里挑两个数,用任意运算符计算出结果,把这个结果和剩下的数字组成新的集合,重复这个过程直到只剩一个数。这样所有可能的括号组合(也就是所有运算顺序)都会被覆盖。
具体步骤
- 数字组合处理:无需提前生成全排列,递归时直接从原列表选两个不同元素即可,选不同位置的元素已经包含了排列的所有情况。
- 递归计算所有结果:
- 若当前数字列表只剩1个元素,返回该元素作为可能结果。
- 遍历所有两两组合的数字对(
i≠j)。 - 对每对数字,遍历四种运算符:
- 加法:
a + b(交换律成立,只需算一次) - 减法:
a - b和b - a(不满足交换律,两种情况都要计算) - 乘法:
a * b(交换律成立,只需算一次) - 除法:
a / b和b / a(不满足交换律,且需确保除数不为0)
- 加法:
- 将计算结果与剩余数字组成新列表,递归调用函数并收集所有返回结果。
- 结果筛选:收集所有可能结果后,先检查是否存在接近24的数(因浮点数精度问题,用
abs(num - 24) < 1e-6判断);若存在直接输出24,否则筛选出所有小于24的数取最大值。
简单Python代码框架
def compute_possible(nums): n = len(nums) if n == 1: return {nums[0]} results = set() # 遍历所有两两组合的索引 for i in range(n): for j in range(n): if i == j: continue # 提取剩余数字 rest = [nums[k] for k in range(n) if k != i and k != j] a, b = nums[i], nums[j] # 加法 results.update(compute_possible(rest + [a + b])) # 减法两种情况 results.update(compute_possible(rest + [a - b])) results.update(compute_possible(rest + [b - a])) # 乘法 results.update(compute_possible(rest + [a * b])) # 除法两种情况,避免除以0 if b != 0: results.update(compute_possible(rest + [a / b])) if a != 0: results.update(compute_possible(rest + [b / a])) return results def solve_24(nums): possible = compute_possible(nums) # 处理浮点数精度,判断是否存在24 has_24 = any(abs(x - 24) < 1e-6 for x in possible) if has_24: return 24 # 筛选小于24的数,取最大值 candidates = [x for x in possible if x < 24 + 1e-6] return max(candidates) if candidates else min(possible) # 测试示例:3,3,8,8 应该输出24 print(solve_24([3,3,8,8]))
关键注意事项
- 浮点数精度:不能直接用
x == 24判断,必须设置误差范围,避免因除法产生的浮点精度损失导致误判。 - 去重优化:用集合存储结果可自动去重,避免重复计算相同数值,提升运行效率。
- 重复数字处理:输入含重复数字时,递归过程会自动处理,无需额外生成全排列,集合会自动合并相同结果。
内容的提问来源于stack exchange,提问作者Faheem Azeemi
相关产品推荐
相关产品推荐

