题解
纸牌斗地主
1 条题解
-
0
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