C++笔试编程题1:雀魂启动

2019字节跳动笔试编程题

雀魂启动

小包最近迷上了一款叫做雀魂的麻将游戏,但是这个游戏规则太复杂,小包玩了几个月了还是输多赢少。
于是生气的小包根据游戏简化了一下规则发明了一种新的麻将,只留下一种花色,并且去除了一些特殊和牌方式(例如七对子等),具体的规则如下:
总共有36张牌,每张牌是1~9。每个数字4张牌。
你手里有其中的14张牌,如果这14张牌满足如下条件,即算作和牌

  • 14张牌中有2张相同数字的牌,称为雀头。
  • 除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)

例如:
1 1 1 2 2 2 6 6 6 7 7 7 9 9 可以组成1,2,6,7的4个刻子和9的雀头,可以和牌
1 1 1 1 2 2 3 3 5 6 7 7 8 9用1做雀头,组123,123,567,789的四个顺子,可以和牌
1 1 1 2 2 2 3 3 3 5 6 7 7 9 无论用1 2 3 7哪个做雀头,都无法组成和牌的条件。

现在,小包从36张牌中抽取了13张牌,他想知道在剩下的23张牌中,再取一张牌,取到哪几种数字牌可以和牌。

  • 输入一行,包含13个数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。
  • 输出一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0

输入1 1 1 2 2 2 5 5 5 6 6 6 9
输出9可以组成1,2,6,7的4个刻子和9的雀头
输入1 1 1 1 2 2 3 3 5 6 7 8 9
输出4 7用1做雀头,组123,123,567或456,789的四个顺子
输入1 1 1 2 2 2 3 3 3 5 7 7 9
输出0来任何牌都无法和牌

备注:请不要根据自己的常识为题目增加未提及的条件。对于20%的数据,保证和牌时一定是4个刻子+雀头的形式

代码:

#include
#include
#include
using namespace std;
bool ishu(vector<int>num)
{
    if (num.empty())return true;
    int count0 = 0;
    for(int i=0;i<num.size();++i){
        if (num[0] == num[i])
            ++count0;
        else break;
    }//第一个元素出现的次数为count0
    if (num.size() % 3 != 0 && count0 >= 2){
        //尝试将第一个元素作为雀头
        vector<int> newnum(num.begin() + 2, num.end());
        if (ishu(newnum))
            return true;
    }
    //若第一个元素不能作为雀头,且大于三次
    if (count0 >= 3){
        vector<int> newnum(num.begin() + 3, num.end());
        if (ishu(newnum))//将重复的第一个元素去掉,遍历到第二个元素
            return true;
    }
    //如果元素的后两个元素都存在,那么把后两个元素都删掉一个
    if(count(num.begin(),num.end(),num[0]+1)>0 && count(num.begin(), num.end(), num[0] + 2)>0)
    {
        vector<int> newnum(num.begin() + 1, num.end());
        newnum.erase(find(newnum.begin(), newnum.end(), num[0] + 1));
        newnum.erase(find(newnum.begin(), newnum.end(), num[0] + 2));
        if (ishu(newnum))
            return true;
    }
    return false;
}
bool hupai(vector<int>num, int n)
{
    if (count(num.begin(), num.end(), n) == 4)//如果n已经出现4次了,那么不能再加n
        return false;
    num.push_back(n);//将尝试的元素加入到数组中
    sort(num.begin(),num.end());
    return ishu(num);//判断是否胡牌
}
int main()
{
    vector<int> num;
    vector<int> res;
    for (int i = 0; i < 13; ++i){
        int tmp;
        cin >> tmp;
        num.push_back(tmp);
    }
    for (int n = 1; n < 10; ++n){
        if (hupai(num, n))//挨个试是否能胡牌,总共也就10种选择
            res.push_back(n);
    }
    if (res.empty())
        cout << 0;
    else
        for (int i = 0; i < res.size(); ++i)
            cout << res[i]<<" ";
}

C++ count函数的用法

algorithm头文件定义了一个count的函数,其功能类似于find。
这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果
count(first,last,value); first是容器的首迭代器,last是容器的末迭代器,value是询问的元素。

#include 
#include
#include
using namespace std;
 int main(){
	//count函数的用法
	vector<int> v(10,1);
	int a[10] = { 1, 2, 3, 4, 4, 4, 4 }; 
	//向量计数
	cout << count(v.begin(), v.end(), 1) << endl;
	//数组计数
	cout << count(a, a + 10, 1) << endl;
	return 0;
}

C++ count_if函数的用法

count(first,last,pred); first是容器的首迭代器,last是容器的末迭代器,pred是元素被计数的满足条件。
可以用来在序列中统计与某谓词匹配的次数。

#include 
#include 
#include 
bool greater10(int value){
    return value >10;
}
int main(){
    using namespace std;
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(10);
    result1 = count_if(v1.begin(), v1.end(), greater10);
    cout << "大于10的元素个数为: "<< result1<< endl;
}

C++ find函数的用法

find函数使用一对迭代器和一个值做参数,返回这个值第一次出现的位置
find(first,last,value);

#include 
#include 
#include 
using namespace std;
int main(){
    vector<string> m;
    m.push_back("hello");
    if (find(m.begin(), m.end(), "hello") == m.end())
        cout << "no" << endl;
    else
        cout << "yes" << endl;
}

C++ erase函数的用法

c.erase(p) 删除迭代器p所指向的元素,返回一个指向被删元素之后元素的迭代器,若p指向尾元素,则返回尾后迭代器,若p是尾后迭代器,则会产生未定义行为。

你可能感兴趣的:(笔试编程题)