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;
}