【leetcode】679. 24 点游戏(回溯 / dfs)

这里写目录标题

  • 题目
  • 解法
    • 回溯
    • DFS深度优先算法

题目

你有 4 张写有 1 到 9 数字的牌。你需要判断是否能通过 *,/,+,-,(,) 的运算得到 24。

示例 1:

输入: [4, 1, 8, 7]
输出: True
解释: (8-4) * (7-1) = 24

示例 2:

输入: [1, 2, 1, 2]
输出: False

注意:

  • 除法运算符 / 表示实数除法,而不是整数除法。例如 4 / (1 - 2/3) = 12 。
  • 每个运算符对两个数进行运算。特别是我们不能用 - 作为一元运算符。例如,[1, 1, 1, 1] 作为输入时,表达式 -1 - 1 - 1 - 1 是不允许的。
  • 你不能将数字连接在一起。例如,输入为 [1, 2, 1, 2] 时,不能写成 12 + 12 。

解法

回溯

对于数字a,b存在6种运算:

  • a + b (满足交换律)
  • a * b (满足交换律)
  • a - b、 b - a
  • a / b、b / a

那么每次都选出2个数字进行6种运算操作

  1. 第1轮:从4个数字中选出2个
  2. 第2轮:从剩下3个数字中选出2个
  3. 第3轮:从剩下2个数字中选出2个
  4. 第2轮:判断结果

注意:
le-6是浮点计算的精度误差,这里判断误差是否小于1e-6,这样就是正确结果

class Solution {
public:
    bool judgePoint24(vector<int>& nums) {
        double a = nums[0], b = nums[1], c = nums[2], d = nums[3];
        return judgePoint24_4(a,b,c,d);
    }
    //第1轮:从4个数字中选2个进行六次可能的操作
    bool judgePoint24_4(double a, double b, double c, double d){
        return  judgePoint24_3( a + b, c, d)|| //a,b
                judgePoint24_3( a * b, c, d)||
                judgePoint24_3( a - b, c, d)||
                judgePoint24_3( b - a, c, d)||
                judgePoint24_3( a / b, c, d)||
                judgePoint24_3( b / a, c, d)||
                judgePoint24_3( a + c, b, d)|| //a,c
                judgePoint24_3( a * c, b, d)||
                judgePoint24_3( a - c, b, d)||
                judgePoint24_3( c - a, b, d)||
                judgePoint24_3( a / c, b, d)||
                judgePoint24_3( c / a, b, d)||
                judgePoint24_3( a + d, b, c)|| // a,d
                judgePoint24_3( a * d, b, c)|| 
                judgePoint24_3( a - d, b, c)|| 
                judgePoint24_3( d - a, b, c)|| 
                judgePoint24_3( a / d, b, c)|| 
                judgePoint24_3( d / a, b, c)|| 
                judgePoint24_3( b + c, a, d)|| // b,c
                judgePoint24_3( b * c, a, d)|| 
                judgePoint24_3( b - c, a, d)|| 
                judgePoint24_3( c - b, a, d)|| 
                judgePoint24_3( b / c, a, d)|| 
                judgePoint24_3( c / b, a, d)|| 
                judgePoint24_3( b + d, a, c)|| // b,d
                judgePoint24_3( b * d, a, c)|| 
                judgePoint24_3( b - d, a, c)|| 
                judgePoint24_3( d - b, a, c)|| 
                judgePoint24_3( b / d, a, c)|| 
                judgePoint24_3( d / b, a, c)|| 
                judgePoint24_3( c + d, a, b)|| // c,d
                judgePoint24_3( c * d, a, b)|| 
                judgePoint24_3( c - d, a, b)|| 
                judgePoint24_3( d - c, a, b)|| 
                judgePoint24_3( c / d, a, b)|| 
                judgePoint24_3( d / c, a, b);
    }
    //第2轮:从3个数字中选2个进行六次可能的操作
    bool judgePoint24_3(double a, double b, double c){
        return  judgePoint24_2( a + b, c) || // a,b
                judgePoint24_2( a * b, c) ||
                judgePoint24_2( a - b, c) ||
                judgePoint24_2( b - a, c) ||
                judgePoint24_2( a / b, c) ||
                judgePoint24_2( b / a, c) ||
                judgePoint24_2( a + c, b) || // a,c
                judgePoint24_2( a * c, b) ||
                judgePoint24_2( a - c, b) ||
                judgePoint24_2( c - a, b) ||
                judgePoint24_2( a / c, b) ||
                judgePoint24_2( c / a, b) ||
                judgePoint24_2( b + c, a) || // b,c
                judgePoint24_2( b * c, a) ||
                judgePoint24_2( b - c, a) ||
                judgePoint24_2( c - b, a) ||
                judgePoint24_2( b / c, a) ||
                judgePoint24_2( c / b, a) ;
    }
    //第3轮:从2个数字中选2个进行六次可能的操作
    bool judgePoint24_2(double a, double b){
        return  judgePoint24_1( a + b ) ||
                judgePoint24_1( a * b ) ||
                judgePoint24_1( a - b ) ||
                judgePoint24_1( b - a ) ||
                judgePoint24_1( a / b ) ||
                judgePoint24_1( b / a ) ;
    }
    //第4轮:对最终结果进行24判定
    bool judgePoint24_1(double result){
        // return result == 24.0; //测试用例[3,3,8,8]不会通过:8/(3-8/3)=24
        // le-6是浮点计算的精度误差,这里判断误差小于1e-6,这样就是正确结果
        return abs(result - 24) < 1e-6;
    }
};

【leetcode】679. 24 点游戏(回溯 / dfs)_第1张图片

DFS深度优先算法

class Solution {
public:
    
    bool judgePoint24(vector<int>& nums) {
        if(nums.size()!=4) return false;
        vector<double> vec;
        for(int i=0; i<nums.size(); i++)
            vec.push_back(nums[i]);
        return dfs(vec);
    }
    bool dfs(vector<double>& vec){
        if(vec.size() == 0) return false;
        if(vec.size() == 1){
            return abs(vec[0]-24) < 1e-6;
        }
        for(int i=0; i<vec.size(); i++){
            for(int j=i+1; j<vec.size(); j++){
                //每次取出两个数进行6种运算,将其余数都保存
                vector<double> newvec;
                double a = vec[i], b = vec[j], r;
                for( int k=0; k<vec.size(); k++){
                    if(k!=i&&k!=j) newvec.push_back(vec[k]);
                }
                //每次尝试都将运算结果保存,如果尝试失败注意还原操作
                for(int k=0; k<6; k++){
                    if(k==0){
                        r = a + b;
                    }else if(k==1){
                        r = a - b;
                    }else if(k==2){
                        r = b - a;
                    }else if(k==3){
                        r = a * b;
                    }else if(k==4){
                        if( b == 0) continue;
                        r = a / b;
                    }else if(k==5){
                        if( a == 0) continue;
                        r = b / a;
                    }
                    newvec.push_back(r);
                    if( dfs(newvec) ) return true;
                    newvec.pop_back(); // 还原操作,删除最后一个元素即刚刚的运算结果
                }
            }
        }
        return false;
    }
};

【leetcode】679. 24 点游戏(回溯 / dfs)_第2张图片

你可能感兴趣的:(leetcode)