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,感觉可以面试谷歌了?

posted @ 2019-09-17 20:59  于老师的父亲王老爷子  阅读(7)  评论(0编辑  收藏  举报