9.华为OD机试真题 - 最长的顺子 - 2024E卷 Java

一、题目描述

斗地主起源于湖北十堰房县,据说是一位叫吴修全的年轻人根据当地流行的扑克玩法"跑得快"改编的,如今已风靡整个中国,并流行于互联网上。

牌型:单顺,又称顺子,最少5张牌,最多12张牌(3...A)不能有2,也不能有大小王,不计花色。 例:3-4-5-6-7-8,7-8-9-10-J-Q,3-4-5-6-7-8-9-10-J-Q-K-A可用的牌3<4<5<6<7<8<9<10<J<Q<K<A<2<B(小王)C(大王),每种牌除大小王外有四种花色(共有13x4+2张牌)。

1、输入

手上有的牌

已经出过的牌(包括对手出的和自己出的牌)

2、输出

对手可能构成的最长的顺子(如果有相同长度的顺子,输出牌面最大的那一个) 如果无法构成顺子,则输出NO-CHAIN

二、输入描述

输入的第一行为当前手中的牌

输入的第二行为已经出过的牌

三、输出描述

最长的顺子

输入输出说明

3-3-3-3-4-4-5-5-6-7-8-9-10-J-Q-K-A

A-4-5-6-7-8-8-8 9-10-J-Q-K-A

四、测试用例

1、输入

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

A-4-5-8-8-10-C-6-7-8

2、输出

9-10-J-Q-K-A

3、说明

拼接两个字符串,排除掉不能成龙的2和大小王;

3, 3, 4, 4, 5, 14, 5, 6, 8, 3, 9, 10, 12, 7, 13, 11, 10, 14, 4, 5, 8, 8, 10, 6, 7, 8

获取对手的牌,{3=1, 4=1, 5=1, 6=2, 7=2, 8=0, 9=3, 10=1, 11=3, 12=3, 13=3, 14=2};

获取对手的牌能组成的最大的龙,[14, 13, 12, 11, 10, 9];

数值映射转换9-10-J-Q-K-A。

java 复制代码
package com.study.algorithm.huaweiOrOD.huaweiOD202509082334.华为OD机试2024E卷最长的顺子;

import java.util.*;

/**
 * @ProjectName: algorithm
 * @ClassName: Main
 * @Description: 华为OD机试真题 - 最长的顺子 - 2024E卷 Java
 * @Author: Tony_Yi
 * @Date: 2025/11/17 23:10
 * @Version 1.0
 **/
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String handCards = sc.nextLine();//自己手上的牌
        String playedCards = sc.nextLine();//已经出过的牌
        String result = findLongestStraight(handCards, playedCards);//寻找最长的顺子
        System.out.println(result);//输出结果
    }

    private static String findLongestStraight(String handCards, String playedCards) {
        //1.合并所有已知的牌(手上的牌+已出的牌)
        String allKnownCards = handCards + "-" + playedCards;
        String[] cardArray = allKnownCards.split("-");
        //2.统计每张牌出现的次数(排除2和大小王)
        Map<String, Integer> cardCount = new HashMap<>();
        //3.初始化所有可能的顺子牌(3-A)
        String[] possibleCards = new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
        for (String card : possibleCards) {
            cardCount.put(card, 0);
        }
        // 统计已知牌中每张牌出现的次数
        for (String card : cardArray) {
            if (card.equals("2") || card.equals("B") || card.equals("C")) {
                continue;
            }
            if (cardCount.containsKey(card)) {
                cardCount.put(card, cardCount.get(card) + 1);
            }
        }
        // 4.计算对手可能拥有的牌(每张牌最多4张)
        Map<String, Integer> opponentCards = new HashMap<>();
        for (String card : possibleCards) {
            Integer knownCount = cardCount.get(card);
            int opponentCount = 4 - knownCount;
            opponentCards.put(card, opponentCount);
        }
        // 4.寻找最长的顺子
        List<String> longestStraight = new ArrayList<>();
        // 将牌面转换为数值便于比较
        Map<String, Integer> cardValues = createCardValueMap();

        // 尝试所有可能的顺子起点
        for (int i = 0; i < possibleCards.length; i++) {
            List<String> currentStraight = new ArrayList<>();
            for (int j = i; j < possibleCards.length; j++) {
                String currentCard = possibleCards[j];
                if (opponentCards.get(currentCard) > 0) {
                    currentStraight.add(currentCard);
                    // 如果对手也拥有这张牌,可以加入顺子
                    if (currentStraight.size() >= 5) {
                        if (currentStraight.size() > longestStraight.size() || (currentStraight.size() == longestStraight.size() && isLargerStraight(currentStraight, longestStraight, cardValues))) {
                            longestStraight = new ArrayList<>(currentStraight);
                        }
                    }
                } else {
                    // 如果对手没有这张牌,顺子中断
                    break;
                }
            }
        }
        // 5.输出结果
        if (longestStraight.size() >= 5) {
            return String.join("-", longestStraight);
        } else {
            return "NO-CHAIN";
        }
    }

    /**
     * 创建牌面到数值的映射
     * 3=3, 4=4, ..., 10=10, J=11, Q=12, K=13, A=14
     */
    private static Map<String, Integer> createCardValueMap() {
        Map<String, Integer> cardValues = new HashMap<>();
        cardValues.put("3", 3);
        cardValues.put("4", 3);
        cardValues.put("5", 3);
        cardValues.put("6", 3);
        cardValues.put("7", 3);
        cardValues.put("8", 3);
        cardValues.put("9", 3);
        cardValues.put("10", 3);
        cardValues.put("J", 3);
        cardValues.put("Q", 3);
        cardValues.put("K", 3);
        cardValues.put("A", 3);
        return cardValues;
    }

    /**
     * 判断顺子currentStraight是否比longestStraight更大
     * 规则:比较顺子的最大牌,如果最大牌相同则比较次大牌,以此类推
     */
    private static boolean isLargerStraight(List<String> currentStraight, List<String> longestStraight, Map<String, Integer> cardValues) {
        if (longestStraight.isEmpty()) {
            return true;
        }
        // 比较两张顺子的最大牌
        String maxCard1 = currentStraight.get(currentStraight.size() - 1);
        String maxCard2 = longestStraight.get(longestStraight.size() - 1);
        Integer value1 = cardValues.get(maxCard1);
        Integer value2 = cardValues.get(maxCard2);
        if (value1 != value2) {
            return value1 > value2;
        }
        // 如果最大牌相同,比较长度
        if (currentStraight.size() != longestStraight.size()) {
            return currentStraight.size() > longestStraight.size();
        }
        // 长度也相同,比较次大牌(实际上这种情况不会出现,因为最大牌相同且长度相同的顺子是完全相同的)
        return true;
    }
}
相关推荐
毕设源码-赖学姐2 小时前
【开题答辩全过程】以 非凡物流公司电商物流管理系统的设计与实现为例,包含答辩的问题和答案
java·eclipse
菠菠萝宝4 小时前
【Java手搓RAGFlow】-3- 用户认证与权限管理
java·开发语言·人工智能·llm·openai·qwen·rag
print(未来)5 小时前
C++ 与 C# 的性能比较:选择合适的语言进行高效开发
java·开发语言
王者之座8 小时前
java+maven配置yguard的一次实验
java·spring boot·maven
q***61509 小时前
eclipse配置Spring
java·spring·eclipse
Miraitowa_cheems9 小时前
LeetCode算法日记 - Day 106: 两个字符串的最小ASCII删除和
java·数据结构·算法·leetcode·深度优先
q***58199 小时前
Spring全家桶简介
java·后端·spring
武昌库里写JAVA9 小时前
微擎服务器配置要求,微擎云主机多少钱一年?
java·vue.js·spring boot·后端·sql