You have 4 cards each containing a number from 1 to 9. You need to judge whether they could operated through *, /, +, -, (, ) to get the value of 24.
思路:
开始自己的思路是遍历每个数字,然后考虑数字后面是否加符号,是否能加括号,最后再对搜索完的算术表达式求解,这个思路有两个地方都卡住了,一个是何时能加括号,一个是对最后表达式求解的问题。
最后看答案,豁然开朗,无论怎么加括号,最后的计算结果都是两个数的运算结果,而最后两个数的其中一个数是由前三个数运算而来,由此可以层层向上反推,即先求解任意两个数所有可能的运算结果,然后把它和剩下的两个数组合,递归求解下去,这样的过程就包含了括号可能导致的各种运算顺序情况。
private double score = 24;
private double esp = 0.001;
public boolean judgePoint24(int[] nums) {
if (nums == null || nums.length != 4) {
return false;
}
List<Double> dnums = new ArrayList<>();
for (int num : nums) {
dnums.add((double)num);
}
return helper(dnums);
}
private boolean helper(List<Double> dnums) {
if (dnums.size() == 1 && Math.abs(dnums.get(0) - score) < esp) {
return true;
}
for (int i = 0; i < dnums.size(); i++) {
for (int j = i + 1; j < dnums.size(); j++) {
List<Double> next = new ArrayList<>();
double n1 = dnums.get(i), n2 = dnums.get(j);
next.addAll(Arrays.asList(n1+n2, n1-n2, n2-n1, n1*n2));
if (Math.abs(n1) > esp) {
next.add(n2/n1);
}
if (Math.abs(n2) > esp) {
next.add(n1/n2);
}
dnums.remove(i);
dnums.remove(j);
for (double tmp : next) {
dnums.add(tmp);
if (helper(dnums)) {
return true;
}
dnums.remove(tmp);
}
dnums.add(j, n2);
dnums.add(i, n1);
}
}
return false;
}