华为机试扑克牌顺子、扑克牌摆顺子玩法

  • 扑克牌顺子问题详解
  • 问题一:判断五张牌是否为顺子

    问题描述

    从扑克牌中随机抽取5张牌,判断这5张牌是否是顺子(即连续)。其中:

  • 2~10为数字本身
  • A为1,J为11,Q为12,K为13
  • 大小王(Joker)可以代表任意数字(通常用0表示)
  • 解题思路

    核心思想

    1. 排序数组:便于分析连续性

    2. 统计大小王数量:可以作为万能牌填补空缺

    3. 计算间隔总数:统计非0数字之间的间隔数

    4. 检查重复:除0外,其他数字不可重复

    关键条件

  • 最大间隔数 ≤ 大小王数量
  • 无重复的非0数字
  • Python实现

    python

    def is_straight(cards):

    判断五张扑克牌是否为顺子

    Args:

    cards: 包含5个整数的列表,0表示大小王

    Returns:

    bool: 是否为顺子

    if len(cards) != 5:

    return False

    # 排序

    cards.sort

    # 统计大小王数量

    zero_count = cards.count(0)

    # 检查是否有重复的非0牌

    for i in range(zero_count, 4):

    if cards[i] == cards[i + 1]:

    return False

    # 计算间隔总数

    gap = 0

    for i in range(zero_count, 4):

    gap += cards[i + 1]

  • cards[i]
  • 1
  • return gap

    # 测试用例

    def test_is_straight:

    test_cases = [

    [1, 2, 3, 4, 5], # True: 正常顺子

    [0, 0, 1, 2, 3], # True: 双王补位

    [0, 0, 0, 0, 1], # True: 四王补位

    [1, 3, 4, 5, 6], # False: 缺2

    [0, 0, 2, 3, 6], # False: 缺4,5,王不够

    [1, 2, 3, 4, 4], # False: 有重复

    [11, 12, 13, 0, 0] # True: J,Q,K + 双王

    for i, cards in enumerate(test_cases):

    result = is_straight(cards)

    print(f"测试用例 {i+1}: {cards} -> {'是顺子' if result else '不是顺子'}")

    test_is_straight

    C++实现

    cpp

    #include

    #include

    #include

    using namespace std;

    bool isStraight(vector& cards) {

    if (cards.size != 5) return false;

    // 排序

    sort(cards.begin, cards.end);

    // 统计大小王数量

    int zeroCount = 0;

    for for (int card : cards) {

    if (card == 0) zeroCount++;

    // 检查重复并计算间隔

    int gap = 0;

    for (int i = zeroCount; i

    if (cards[i] == cards[i + 1]) return false;

    gap += cards[i + 1]

  • cards[i]
  • 1;
  • return gap

    // 测试函数

    void testIsStraight {

    vector> testCases = {

    {1, 2, 3, 4, 5},

    {0, 0, 1, 2, 3},

    {0, 0, 0, 0, 1},

    {1, 3, 4, 5, 6},

    {0, 0, 2, 3, 6},

    {1, 2, 3, 4, 4},

    {11, 12, 13, 0, 0}

    };

    for (int i = 0; i

    bool result = isStraight(testCases[i]);

    cout

    for (int card : testCases[i]) cout

    cout "

    int main {

    testIsStraight;

    return 0;

    问题二:扑克牌摆顺子玩法(扩展)

    问题描述

    给定一副牌(可能包含大小王),如何摆放才能形成最多的顺子?每个顺子至少包含3张牌。

    解题思路

    贪心策略

    1. 统计频率:记录每个数字出现的次数

    2. 优先组成小顺子:从最小数字开始尝试组成顺子

    3. 动态调整:根据剩余的王牌数量决定顺子长度

    Python实现

    python

    def max_straights(cards):

    计算最多能组成的顺子数量

    Args:

    华为机试扑克牌顺子、扑克牌摆顺子玩法

    cards: 扑克牌列表,0表示大小王

    Returns:

    int: 最多顺子数量

    from collections import Counter

    # 统计非王牌频率

    freq = Counter([card for card in cards if card != 0])

    jokers = cards.count(0)

    straights = 0

    # 按顺序处理每个可能的起始点

    for start in range(1, 12): # 顺子最大到K(13),起始点最大为11

    while True:

    # 尝试组成从start开始的顺子

    length = 3 # 顺子最小长度为3

    # 检查能否组成更长顺子

    current_jokers =okers = jokers

    can_form = True

    aapoker官方下载中心

    for i in range(start, start + length):

    if freq[i] > 0:

    freq[i] -= 1

    elif current_jokers > 0:

    current_jokers -= 1

    else:

    can_form = False

    break

    if can_form:

    straights += 1

    jokers = current_jokers

    else:

    break

    return straights

    # 测试

    test_cards = [1, 2, 3, 4, 5, 6, 0, 0] # 1-6 + 两个王

    print(f"最多可以组成 {max_straights(test_cards)} 个顺子")

    复杂度分析

    问题一

  • 时间复杂度:O(1)
  • 固定5张牌
  • 空间复杂度:O(1)
  • 问题二

  • 时间复杂度:O(n)
  • n为牌的数目
  • 空间复杂度:O(1)
  • 使用固定大小的频率表
  • 这两个问题考察了以下算法技能:

    1. 数组操作:排序、遍历

    2. 逻辑推理:间隔计算、条件判断

    3. 贪心思想:局部最优解构成全局最优解

    4. 边界情况处理:重复数字、王牌使用

    掌握这些问题有助于提升在华为机试中的表现!