问题描述
679.24 点游戏
你有 4 张写有 1 到 9 数字的牌。你需要判断是否能通过 *,/,+,-,(,) 的运算得到 24。
示例 1:
输入: [4, 1, 8, 7]
输出: True
解释: (8-4) * (7-1) = 24
示例 2:
输入: [1, 2, 1, 2]
输出: False
注意:
- 除法运算符 / 表示实数除法,而不是整数除法。例如 4 / (1 - 2/3) = 12 。
- 每个运算符对两个数进行运算。特别是我们不能用 - 作为一元运算符。例如,[1, 1, 1, 1] 作为输入时,表达式 -1 - 1 - 1 - 1 是不允许的。
- 你不能将数字连接在一起。例如,输入为 [1, 2, 1, 2] 时,不能写成 12 + 12 。
题解
使用回溯法解决
一共有4个数和4个操作符,分3步解决
- 从4个数中选2个数,从4个操作符中选一个操作符进行计算,将计算结果与剩下的2个数组成一个新的集合,然后判断这3个数能否得到24。第1步一共有
种情况。 - 从剩下3个数中选2个数进行计算,将计算结果与最后1个数组成新的集合。第2步一共有
种情况。 - 计算最后两个数,第3步一共有
种情况。
48 * 24 * 8 = 9216
一共有9216种算式组合,只要有一个结果等于24,就返回true,否则返回false。
由于除法表示实数除法,而不是整数除法,所以要用浮点数存储。
最后还要处理精度问题,设定一个误差值,只要误差不超过这个范围就忽略
class Solution {
public boolean judgePoint24(int[] nums) {
List<Double> list = new ArrayList<>();
for (double num : nums) {
list.add(num);
}
return solve(list);
}
char[] opers = { '+', '*', '-', '/' };
private boolean solve(List<Double> list) {
int size = list.size();
if (size == 0)
return false;
if (size == 1)
return Math.abs(list.get(0) - 24) < 1e-6;
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
List<Double> list2 = new ArrayList<>();
for (int k = 0; k < size; k++) {
if (k != i && k != j) {
list2.add(list.get(k));
}
}
for (int k = 0; k < 4; k++) {
list2.add(operate(list.get(i), list.get(j), opers[k]));
if (solve(list2)) {
return true;
}
list2.remove(size - 2);
if (k > 1) {
list2.add(operate(list.get(j), list.get(i), opers[k]));
if (solve(list2)) {
return true;
}
list2.remove(size - 2);
}
}
}
}
return false;
}
private double operate(double a, double b, char oper) {
switch (oper) {
case '+':
return a + b;
case '*':
return a * b;
case '-':
return a - b;
case '/':
if (!(Math.abs(b) < 1e-6)) return a / b;
default:
return 0;
}
}
}