【华为机试-200/中等】斗地主之顺子

斗地主之顺子

题目描述:

  • 在斗地主扑克牌游戏中, 扑克牌由小到大的顺序为:3,4,5,6,7,8,9,10,J,Q,K,A,2,
  • 玩家可以出的扑克牌阵型有:单张、对子、顺子、飞机、炸弹等。
  • 其中顺子的出牌规则为:由 至少 5 张由小到大连续递增 的扑克牌组成,且 不能包含 2 。
  • 例如:{3,4,5,6,7}、{3,4,5,6,7,8,9,10,J,Q,K,A}都是有效的顺子;
  • 而{J,Q,K,A,2}、 {2,3,4,5,6}、{3,4,5,6}、{3,4,5,6,8}等都不是顺子。
  • 给定一个包含13张牌的数组,如果有满足出牌规则的顺子,请输出顺子。
  • 如果存在多个顺子,请每行输出一个顺子,且需要按顺子的 第一张牌的大小(必须从小到大) 依次输出。
  • 如果没有满足出牌规则的顺子,请 输出 No 。

输入描述:

13张任意顺序的扑克牌,每张扑克牌数字用空格隔开,每张扑克牌的数字都是合法的,并且不包括大小王:

2 9 J 2 3 4 K A 7 9 A 5 6

不需要考虑输入为异常字符的情况

输出描述: 组成的顺子,每张扑克牌数字用空格隔开:

3 4 5 6 7

示例1:

输入

2 9 J 2 3 4 K A 7 9 A 5 6

输出

3 4 5 6 7

说明

13张牌中,可以组成的顺子只有1组:3 4 5 6 7

示例2:

输入

2 9 J 10 3 4 K A 7 Q A 5 6

输出

2
3 4 5 6 7
9 10 J Q K A

说明

13张牌中,可以组成2组顺子,从小到大分别为:3 4 5 6 7 和 9 10 J Q K A

示例3:

输入

2 9 9 9 3 4 K A 10 Q A 5 6

输出

No

说明

13张牌中,无法组成顺子


注意:

特殊输入

3 3 4 4 5 5 6 6 7 7 8 8 9

对应输出

2
3 4 5 6 7 8
3 4 5 6 7 8 9

C++题解

#include <bits/stdc++.h>
using namespace std;

// 数字转成牌面字符
string intToStr(int value)
{
    switch (value) {
        case 11:
            return "J";
        case 12:
            return "Q";
        case 13:
            return "K";
        case 14:
            return "A";
        default:
            return to_string(value);
    }
}

// 牌面字符转成数字
int strToInt(string poker)
{
    if (poker == "J") {
        return 11;
    } else if (poker == "Q") {
        return 12;
    } else if (poker == "K") {
        return 13;
    } else if (poker == "A") {
        return 14;
    } else {
        return stoi(poker);
    }
}

int main()
{
    vector<int> num;
    string str;
    while (cin >> str) {
        int value = strToInt(str);
        if (value > 2) { // 顺子只可能包含3,4,5,6,7,8,9,10,J,Q,K,A
            num.push_back(value);
        }
    }
    sort(num.begin(), num.end());

    vector<vector<int>> shunzi; // 所有顺子
    vector<int> vec; // 一条顺子
    while (num.size() >= 5) { // 凑成顺子至少需要5张牌
        vec.push_back(num[0]);
        num.erase(num.begin());

        for (int i = 0; i < num.size(); i++) {
            if (num[i] == vec.back()) { // 相同的牌先保留,待下一轮处理
                continue;
            }
            if (num[i] == vec.back() + 1) { // 符合顺子递增规则
                vec.push_back(num[i]);
                num.erase(num.begin() + i); // 要从原来的数组删除这张牌,避免重复处理
                i--; // 删除了一个元素之后,数组下标要减一
            } else { // 不是递增
                if (vec.size() >= 5) { // 当前已凑成一对顺子
                    shunzi.push_back(vec); // 先把顺子存起来
                }
                vec.clear(); // 清空数组,继续找下一对顺子
            }

        }
        // 注意:一轮结束,还有已凑成的顺子,也要存起来(最后一张牌符合顺子规则的情况)
        if (vec.size() >= 5) {
            shunzi.push_back(vec);
        }
        vec.clear();
    }

    if (shunzi.empty()) { // 没有顺子
        cout << "No" << endl;
        return 0;
    }
    
    sort(shunzi.begin(), shunzi.end()); // 为了满足输出格式,这里必须排序
    for (int i = 0; i < shunzi.size(); i++) {
        for (int j = 0; j < shunzi[i].size(); j++) {
            string poker = intToStr(shunzi[i][j]);
            cout << poker << " ";
        }
        cout << endl;
    }
    
    return 0;
}

(说明:题解是我自己写的,如果有错误,欢迎指出,一起交流下。谢谢!)

全部评论
3,4,5,6,7,8,9,10,J,Q是算一个顺子345678910JQ还是算两个顺子34567,8910JQ?题目也没描述优先最大顺子?
点赞 回复 分享
发布于 2022-04-15 15:35
我好奇的是,3,4,5,6,7,7,8,9,10,J这种怎么算,是算两个顺子还是一个顺子?
点赞 回复 分享
发布于 2022-07-13 14:57

相关推荐

点赞 评论 收藏
分享
喜欢走神的孤勇者练习时长两年半:池是池,发是发,我曾池,我现黑
点赞 评论 收藏
分享
1 6 评论
分享
牛客网
牛客企业服务