先从四个数中,取处两个数,共有6种取法。(由于减法和除法运算不具有交换律,所以应该考虑顺序)共有12种选法
然后从四个符号选出一个来运算,共有4种选法。
还剩下三个数,取出两个数,共有3种选法, 6
然后再运算,共有4种
下面还剩下两个数,取出两个数运算,共有4种 2
12*4*6*4*2*4 = 9216种组合方式
这里做的时候有一个技巧,新开一个数组,用来保存运算后的数据,然后递归到下一层。另外如果注意到+和*法具有交换性,因此可以对加法,乘法运算做剪枝操作。
class Solution {
public:
bool judgePoint24(vector<int>& nums) {
vector<double> newNums;
for(auto num:nums) newNums.push_back(num);
return helper(newNums);
}
bool helper(vector<double> nums){
int n = nums.size();
if(n==1) {
return (abs(nums[0]-24)<0.00001);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
vector<double> newNums;
for(int k=0;k<n;k++){
if(k!=i&&k!=j) newNums.push_back(nums[k]);
}
newNums.push_back(-1);
double a = nums[i];
double b = nums[j];
newNums.back() = a + b;
if(helper(newNums)) return true;
newNums.back() = a - b;
if(helper(newNums)) return true;
newNums.back() = a * b;
if(helper(newNums)) return true;
if(b!=0){
newNums.back() = a/b;
if(helper(newNums)) return true;
}
}
}
}
return false;
}
};
class Solution {
public boolean judgePoint24(int[] nums) {
ArrayList A = new ArrayList<Double>();
for (int v: nums) A.add((double) v);
return solve(A);
}
private boolean solve(ArrayList<Double> nums) {
if (nums.size() == 0) return false;
if (nums.size() == 1) return Math.abs(nums.get(0) - 24) < 1e-6;
for (int i = 0; i < nums.size(); i++) {
for (int j = 0; j < nums.size(); j++) {
if (i != j) {
ArrayList<Double> nums2 = new ArrayList<Double>();
for (int k = 0; k < nums.size(); k++) if (k != i && k != j) {
nums2.add(nums.get(k));
}
for (int k = 0; k < 4; k++) {
if (k < 2 && j > i) continue; // 加法/乘法剪枝操作
if (k == 0) nums2.add(nums.get(i) + nums.get(j));
if (k == 1) nums2.add(nums.get(i) * nums.get(j));
if (k == 2) nums2.add(nums.get(i) - nums.get(j));
if (k == 3) {
if (nums.get(j) != 0) {
nums2.add(nums.get(i) / nums.get(j));
} else {
continue;
}
}
if (solve(nums2)) return true;
nums2.remove(nums2.size() - 1);
}
}
}
}
return false;
}
}