题解 | #24点游戏算法#

24点游戏算法

http://www.nowcoder.com/practice/fbc417f314f745b1978fc751a54ac8cb

题目的主要信息:

  • 给出4个1-10的数字,通过加减乘除,得到数字为24就输出true,否则false
  • 数字允许重复,但每个数字仅允许使用一次,测试用例保证无异常数字

方法一:穷举遍历

具体做法:

四个数字,如下图,一共需要3个运算符,我们可以遍历这个位置的4种运算,计算每种组合的结果,查看是否等于24,同时因为数字的次序可以不确定,我们还需要对这四个数字进行全排列,将全排列的每种结果放入下面的数字框中,与不同的运算符搭配,这样就穷举了所有的可能性,如果这里面都不能组成24,那就是不可能。

alt

注意:调用next_permutation获取全排列的数组必须是由小到大开始的,因此要先排序。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

double cal(double a, double b, char c){ //根据运算符运算结果
    switch(c){
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return a / b;
    }
    return 0;
}

bool check(vector<double>& nums){
    char op[4] = {'+', '-', '*', '/'};
    sort(nums.begin(), nums.end()); //先按照从小到大排
    do{
          for(int i = 0; i < 4; i++) //遍历三个位置的所有可能运算符
              for(int j = 0; j < 4; j++)
                  for(int k = 0; k < 4; k++){
                      double first = cal(nums[0], nums[1], op[i]); //依次运算
                      double second = cal(first, nums[2], op[j]);
                      if(cal(second, nums[3], op[k]) == 24) //判断是否等于24
                          return true;
                  }
      }while(next_permutation(nums.begin(), nums.end())); //依次找到其他排列
    return false;
}

int main(){
    vector<double> nums(4); 
    while(cin >> nums[0] >> nums[1] >> nums[2] >> nums[3]){ //输入4个数字
        if(check(nums))
            cout << "true" << endl;
        else
            cout << "false" << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(1)O(1),4个数字,3个运算符不管怎么全排列,都是常数时间
  • 空间复杂度:O(1)O(1),无额外空间

方法二:递归搜索

具体做法:

我们也可以用递归的方式搜索,每次完整4个数字送入递归函数,使用其中一个数字添加运算符进行运算,就将数组中去掉这个数字,然后继续递归,最后判断数组为空时结果是否等于24. 需要注意,因为要回溯,所以不能直接去掉原数组中的数字,而是拷贝一份备份来去除。

#include<iostream>
#include<vector>
using namespace std;

bool check(vector<double> nums, double result){ //递归检查能否组成24
    if(nums.empty()) //数组为空,判断等不等于24
        return result == 24;
    for(int i = 0; i < nums.size(); i++){ //遍历剩下的数字
        vector<double> rest(nums);
        rest.erase(rest.begin() + i); //删去使用的数字
        if(check(rest, result + nums[i]) //分别 进行加减乘除4种运算
          || check(rest, result - nums[i])
          || check(rest, result * nums[i])
          || check(rest, result / nums[i]))
            return true;
    }
    return false;
}

int main(){
    vector<double> nums(4); 
    while(cin >> nums[0] >> nums[1] >> nums[2] >> nums[3]){ //输入4个数字
        if(check(nums, 0))
            cout << "true" << endl;
        else
            cout << "false" << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(1)O(1),4个数字,不管怎么搜索回溯,都是常数时间
  • 空间复杂度:O(1)O(1),递归栈深度也为常数
孤帆远影碧空尽 文章被收录于专栏

牛客网各类题单题解~

全部评论
8 8 8 8 第一个false 第二个true, 第二个有问题
2 回复 分享
发布于 2023-02-12 17:50 上海
这个解法有问题,初始调用输入check(nums,0),对于乘法和除法存在问题
2 回复 分享
发布于 2022-06-15 12:16
(a+b)*(c+d)=24这种情况是不是没有考虑
2 回复 分享
发布于 2022-05-09 15:34
100 101 102 24,第一种返回false,第二个算法返回ture,前面的初始0也参与计算,0*100-101+102*24=24(不考虑优先级)
点赞 回复 分享
发布于 2022-07-16 23:43
这个解法有问题。。四个数字会忽略掉第一个,直接计算3个数字得到结果。
1 回复 分享
发布于 2022-03-31 19:44
第一个穷举的时候没考虑数字重复的情况,数字重复只能用一次
1 回复 分享
发布于 2022-03-19 14:07
第二个递归算法初始值设置为 0 存在问题。会导致 0 乘以其中若干数字,只使用剩余元素组成 24 的情况。 例如 4 6 7 3 ,两种方法结果不一致。递归算法判断为 true 是因为可以用 0 乘以 7 3,只需要 4 和 6 就可以组成 24
点赞 回复 分享
发布于 01-18 21:35 山东
9 6 4 1 怎么会是24呀
点赞 回复 分享
发布于 2023-06-17 17:16 北京
妙啊,一个递推一个递归
点赞 回复 分享
发布于 2023-01-10 16:15 江苏
必须要把4个数全部用完吗?
点赞 回复 分享
发布于 2022-08-10 18:05
但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。 话说题目中这一句是什么意思啊
点赞 回复 分享
发布于 2022-07-05 22:04
1 1 6 6 无法通过,这题我看好多都没考虑重复的有的跑通有的不可以,卧槽真玄学。
点赞 回复 分享
发布于 2022-03-19 16:19

相关推荐

不愿透露姓名的神秘牛友
02-24 17:04
点赞 评论 收藏
分享
老粉都知道小猪猪我很久没更新了,因为秋招非常非常不顺利,emo了三个月了,接下来说一下我的情况吧本人是双非本&nbsp;专业是完全不着计算机边的非科班,比较有优势的是有两段大厂实习,美团和字节。秋招面了50+场泡池子泡死的:滴滴&nbsp;快手&nbsp;去哪儿&nbsp;小鹏汽车&nbsp;不知名的一两个小厂其中字节13场&nbsp;两次3面挂&nbsp;两次2面挂&nbsp;一次一面挂其中有2场面试题没写出来,其他的都是全a,但该挂还是挂,第三次三面才面进去字节,秋招加暑期总共面了22次字节,在字节的面评可以出成书了快手面了8场,2次实习的,通过了但没去,一次2面挂&nbsp;最后一次到录用评估&nbsp;至今无消息滴滴三面完&nbsp;没几天挂了&nbsp;所有技术面找不出2个问题是我回答不上来的,三面还来说我去过字节,应该不会考虑滴滴吧,直接给我干傻了去哪儿一天速通&nbsp;至今无消息小鹏汽车hr&nbsp;至今无消息美团2面挂&nbsp;然后不捞我了,三个志愿全部结束,估计被卡学历了虾皮二面挂&nbsp;这个是我菜,面试官太牛逼了拼多多二面挂&nbsp;3道题也全写了&nbsp;也没问题是回答不出来的&nbsp;泡一周后挂腾讯面了5次&nbsp;一次2面挂&nbsp;三次一面挂,我宣布腾讯是世界上最难进的互联网公司然后还有一些零零散散的中小厂,但是数量比较少,约面大多数都是大厂。整体的战况非常惨烈,面试机会少,就算面过了也需要和各路神仙横向对比,很多次我都是那个被比下去的人,不过这也正常,毕竟谁会放着一个985的硕士不招,反而去招一个双非读化学的小子感觉现在互联网对学历的要求越来越高了,不仅仅要985还要硕士了,双非几乎没啥生存空间了,我感觉未来几年双非想要进大厂开发的难度应该直线上升了,唯一的打法还是从大二刷实习,然后苟个转正,不然要是去秋招大概率是炮灰。而且就我面字节这么多次,已经开始问很多ai的东西了,你一破本科生要是没实习没科研懂什么ai啊,纯纯白给了
不知名牛友_:爸爸
秋招你被哪家公司挂了?
点赞 评论 收藏
分享
评论
23
9
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务