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;
    }
}
相关推荐
铁蛋AI编程实战11 分钟前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python
晚霞的不甘22 分钟前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
SunnyDays101124 分钟前
使用 Java 冻结 Excel 行和列:完整指南
java·冻结excel行和列
摇滚侠35 分钟前
在 SpringBoot 项目中,开发工具使用 IDEA,.idea 目录下的文件需要提交吗
java·spring boot·intellij-idea
云姜.40 分钟前
java多态
java·开发语言·c++
李堇43 分钟前
android滚动列表VerticalRollingTextView
android·java
泉-java1 小时前
第56条:为所有导出的API元素编写文档注释 《Effective Java》
java·开发语言
zfoo-framework1 小时前
帧同步和状态同步
java
charlotte102410242 小时前
高并发:关于在等待学校教务系统选课时的碎碎念
java·运维·网络
亓才孓2 小时前
[JDBC]PreparedStatement替代Statement
java·数据库