top1编程
← 返回题目
题解

纸牌斗地主

1 条题解

  • 0
    @ 2026-8-5 23:52:33

    P4686 纸牌斗地主(入门)

    解题思路

    第一步,理解什么是顺子。 顺子的意思是这些牌的点数是一串连续的数字,比如 1 2 3 4 5 就是顺子,而 2 3 6 8 中间断了,不是顺子。顺子里不能有重复的牌。

    第二步,先排序。 先把牌按点数从小到大排序。排好序之后,如果这手牌是顺子,那么相邻两张牌的点数一定相差 1,也就是后一张牌的点数 = 前一张牌的点数 + 1。

    第三步,检查相邻差。 从头到尾检查一遍:看每一对相邻的牌是不是都满足"后一张比前一张大 1"。只要有一对不满足,就不是顺子;全部满足,就是顺子。用一个标记 ok 记录结果,一旦发现不满足就改成 false 并提前跳出循环。

    第四步,输出答案。 ok 为 true 输出 yes,否则输出 no。

    用例子验证。 输入 1 2 3 4 5,排序后还是 1 2 3 4 5,相邻两张都相差 1,输出 yes。输入 2 3 6 8,排序后 2→3 相差 1,但 3→6 相差 3,输出 no。输入 8 7 6 5 4,排序后是 4 5 6 7 8,相邻都相差 1,是顺子,输出 yes——虽然输入是倒着的,排序后照样判断正确,这就是先排序的好处。

    注意一个特殊情况。 如果出现两张点数相同的牌,比如两个 3,那么相邻两张相差 0,不满足"相差 1",会输出 no,这正好符合顺子的定义(顺子里不能有重复的牌)。

    边界情况: n 最大 13,数组开 1005 保证不越界。记住"排序 + 检查相邻差 1"这个套路,判断顺子就万无一失。

    参考代码

    // P4686 纸牌斗地主:判断n张纸牌是否构成顺子(连续的纸牌),是则输出yes否则no
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int main() {
        int n;
        cin >> n;
        int cards[1005];
        for (int i = 0; i < n; i++) cin >> cards[i];
        sort(cards, cards + n); // 从小到大排序,方便检查是否连续
        bool ok = true;
        for (int i = 1; i < n; i++) {
            if (cards[i] != cards[i - 1] + 1) { // 相邻两张牌必须相差1才算连续
                ok = false;
                break;
            }
        }
        if (ok) cout << "yes" << endl;
        else cout << "no" << endl;
        return 0;
    }
    

    复杂度分析

    排序时间复杂度 O(n log n),检查相邻牌是否连续是一趟 O(n) 的循环。n 最大只有 13,运行时间可以忽略不计。空间复杂度 O(n)。

    • 1