679. 24 Game
又是一个曾经让我畏惧的问题,有人在谷歌中国一面遇到这个题,没用半个小时就理解了哈哈哈,要是早点这么不害怕hard题目多好啊(笑中带泪
总的思路是:
对于一个数组,每次取出两个数(所有可能的组合,顺序不同也算),对它们执行四则运算,把结果存入新的数组,里面还有之前没被取出的数,进入下一次递归。如果数组大小变为了1,就看看这个数是不是24。
class Solution {
public:
bool judgePoint24(vector<int>& nums) {
vector<double> dnums;
for (int num : nums)
dnums.push_back((double)num * 1.0);
return find24(dnums);
}
private:
double eps = 0.00001;
vector<char> ops{'+', '-', '*', '/'};
bool find24(vector<double> nums) {
if (nums.size() == 1) {
return abs(nums[0] - 24) <= eps;
}
for (int i = 0; i < nums.size(); ++i)
for (int j = 0; j < nums.size(); ++j) {
if (i == j)
continue;
vector<double> ret;
for (int k = 0; k < nums.size(); ++k)
if (k != i && k != j)
ret.push_back(nums[k]);
for (char op : ops) {
if (i > j && (op == '*' || op == '+')) continue;//避免重复运算,提高效率
if (nums[j] == 0.0 && op == '/') continue;
switch(op) {
case '+': ret.push_back(nums[i] + nums[j]); break;
case '-': ret.push_back(nums[i] - nums[j]); break;
case '*': ret.push_back(nums[i] * nums[j]); break;
case '/': ret.push_back(nums[i] / nums[j]); break;
}
if (find24(ret))
return true;
ret.pop_back();
}
}
return false;
}
};
一些注意点:
1.这样每次取出两个数,然后运算,可以表示出所有的情况吗?
是可以的。别看有括号,乘除,会有优先级之类的,但是它不也是一个接着一个的算得吗?遍历所有情况,一个一个地算,总会有相同的情况的。
这其实是符合正常思路的,正常计算的话,每次都是取出两个数,得出一个数。
2.乘除法的误差,所以需要有0.00001这一误差值
3.如果是+,*的话,前后顺序没有影响;但是+,-,前后顺序就有影响了,所以我们j也是从0开始,而不是从i+1开始,也就是需要取出所有不同的两个数,顺序不同也算。
ok,感觉可以面试谷歌了?