题目链接:
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 。
しない!全然書きませんでした。。。まったく書かないでください。結局のところ、この質問にはねじれがありません。列挙する限り(ブルートフォース)、状況の数は簡単に計算できます。問題の解決策はこれを行わないだろうと私は感じています、そして私はそれを試すことさえも怠惰です、それはひどいです。。。
注意すべき点がいくつかあります。
- 浮動小数点演算でエラーが発生します設定エラーEPSILON = 1e-6 <EPSILONが同じと見なされる限り
- +および*は交換可能です
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つの関数があります。 。。。