(78)679。24ポイントゲーム(leetcode)

题目链接:
https://leetcode-cn.com/problems/24-game/
难度:困难
679. 24 点游戏
	你有 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 。

しない!全然書きませんでした。まったく書かないでください。結局のところ、この質問にはねじれがありません。列挙する限り(ブルートフォース)、状況の数は簡単に計算できます。問題の解決策はこれを行わないだろうと私は感じています、そして私はそれを試すことさえも怠惰です、それはひどいです。
注意すべき点がいくつかあります。

  1. 浮動小数点演算でエラーが発生します設定エラーEPSILON = 1e-6 <EPSILONが同じと見なされる限り
  2. +および*は交換可能です
class Solution {
    
    
public:
    static constexpr int TAG = 24;
    static constexpr double EPSILON = 1e-6;
    static constexpr int ADD = 0, MULTIPLY = 1, SUBTRACT = 2, DIVIDE = 3;

    bool judgePoint24(vector<int>& nums) {
    
    
        vector<double> vec;
        for(const int& a:nums){
    
    
            vec.emplace_back(static_cast<double>(a));
        }
        // 上面是预处理 将 int 转为 double
        return solve(vec);
    }

    bool solve(vector<double> &vec){
    
    
    	// vec为空 返回false  (按照正常来说 不会有空的)
        if(vec.size()==0){
    
    
            return false;
        }
        // 只剩下一个 判断是否==24
        // fabs 取绝对值
        if(vec.size()==1){
    
    
            return fabs(vec[0]-TAG)<EPSILON;
        }
		
        int n=vec.size();
        // i j 两个循环  在vec中取两个数 进行运算
        for(int i=0;i<n;++i){
    
    
            for(int j=0;j<n;++j){
    
    
            	// 保证 两个数不等
                if(i!=j){
    
    
                	// 将vec中出去 i j 的数存入nvec
                    vector<double> nvec;
                    for(int t=0;t<n;++t){
    
    
                        if(t!=i&&t!=j){
    
    
                            nvec.emplace_back(vec[t]);
                        }
                    }
                    // + - * / 枚举
                    for(int k=0;k<4;++k){
    
    
                    	//  + 和 * 有交换性
                    	// 只需要进行一次即可
                        if(k<2&&i>j){
    
    
                            continue;
                        }
                        // 将对应的运算结果 插入nvec末尾
                        if(k==ADD){
    
    
                            nvec.emplace_back(vec[i]+vec[j]);
                        }else if(k==MULTIPLY){
    
    
                            nvec.emplace_back(vec[i]*vec[j]);
                        }else if(k==SUBTRACT){
    
    
                            nvec.emplace_back(vec[i]-vec[j]);
                        }else if(k==DIVIDE){
    
    
                        	// 若 除数位0跳过
                            if(fabs(vec[j])<EPSILON){
    
    
                                continue;
                            }
                            nvec.emplace_back(vec[i]/vec[j]);
                        }
                        // 递归 nvec中为 
                        // (vec除i j外剩余数) 和 (i j的运算和)
                        if(solve(nvec)){
    
    
                            return true;
                        }
                        // nvec中为 (vec除i j外剩余数)
                        nvec.pop_back();
                    }
                }
            }
        }
        return false;
    }
};

再帰的判断の条件を変えるには時間が長すぎると思います

class Solution {
    
    
public:
    static constexpr int TAG = 24;
    static constexpr double EPSILON = 1e-6;
    static constexpr int ADD = 0, MULTIPLY = 1, SUBTRACT = 2, DIVIDE = 3;

    bool judgePoint24(vector<int>& nums) {
    
    
        vector<double> vec;
        for(const int& a:nums){
    
    
            vec.emplace_back(static_cast<double>(a));
        }
        return solve(vec);
    }

    bool solve(vector<double> &vec){
    
    
        if(vec.size()==2){
    
    
            double x=vec[0];
            double y=vec[1];
            if(fabs(x+y-TAG)<EPSILON||fabs(x*y-TAG)<EPSILON||fabs(x-y-TAG)<EPSILON||fabs(y-x-TAG)<EPSILON){
    
    
                return true;
            }
            if(fabs(x)>EPSILON&&fabs(y/x-TAG)<EPSILON){
    
    
                return true;
            }
            if(fabs(y)>EPSILON&&fabs(x/y-TAG)<EPSILON){
    
    
                return true;
            }
            return false;
        }
        int n=vec.size();
        for(int i=0;i<n;++i){
    
    
            for(int j=0;j<n;++j){
    
    
                if(i!=j){
    
    
                    vector<double> nvec;
                    for(int t=0;t<n;++t){
    
    
                        if(t!=i&&t!=j){
    
    
                            nvec.emplace_back(vec[t]);
                        }
                    }
                    for(int k=0;k<4;++k){
    
    
                        if(k<2&&i>j){
    
    
                            continue;
                        }
                        if(k==ADD){
    
    
                            nvec.emplace_back(vec[i]+vec[j]);
                        }else if(k==MULTIPLY){
    
    
                            nvec.emplace_back(vec[i]*vec[j]);
                        }else if(k==SUBTRACT){
    
    
                            nvec.emplace_back(vec[i]-vec[j]);
                        }else if(k==DIVIDE){
    
    
                            if(fabs(vec[j])<EPSILON){
    
    
                                continue;
                            }
                            nvec.emplace_back(vec[i]/vec[j]);
                        }
                        if(solve(nvec)){
    
    
                            return true;
                        }
                        nvec.pop_back();
                    }
                }
            }
        }
        return false;
    }
};

実行時間は確かに速いです。ただし、再帰条件が2になり、要件を満たしているかどうかを手動で計算する場合、すべての状況を手動で直接シミュレートする愚かな方法はありますか?それから他の人の答えを見ていたとき、本当に4つの選択肢2(4つのルール)-> 3つの選択肢2(4つのルール)-> 2(4つのルール)-> 1(== 24)がありました。合計4つの関数があります。 。

おすすめ

転載: blog.csdn.net/li_qw_er/article/details/108162896