Java语言实现一道经典机考题:斗地主计算对手玩家手上存在的最大顺子

引言

上一段时间笔者所在的甲方公司大规模裁员,笔者也不幸失业了,为了尽快找到新的工作,只好在Boss直聘上一个劲地投简历。不得不说今年的就业行情非常严峻,笔者面试了大半个月竟然一个offer都没收到,很多外包岗位招的虽然是高级开发却要求应聘人员具备架构师才具备的技能和处理生产问题的经验,面试官也不愿冒着一定的风险给我发放offer。

由于今年很多公司裁员,即使很多外包岗位竞争都很激烈。更糟糕的是码农这一行业,过了35岁没做到管理层就会被很多公司嫌弃了,基层码农干到40岁很可能就要被强制退休转行干别的事情去了。笔者自己有时候也很沮丧,明明入行还不足10年,却要思考未来不做程序员了该靠什么赚钱养活自己和一家人?干过这么多年的项目,突然发现作为一名程序员不进入一些大公司不参与一些核心有技术含量的大项目开发,靠平时的自学很难让自己的技术栈提升到能在大公司里独当一面的层次。这次面试就发现一些很好的岗位要求熟练掌握Spark、Flink、Hive和ClickHouse等大数据技术框架,但是自己以往的项目中压根就没用过到过这些技术框架,自己也就没去学过。还有一些优质招聘岗位要求有电商项目和社交IM即时通讯等项目经验或者会安卓App项目开发,这些因为笔者在之前的工作中也没做过同类的项目,因此简历投出去连一个初试的机会都很难收到。

在Boss直聘上投简历的时候收到了很华为OD岗位的面试邀请,看他们的待遇都很不错,都是20-30k 14薪以上,但是却要在面试前参加他们的机考考试,机考有三道题,前两道题100分,最后一道题200分,总分400分,考试总时长150分钟,要考满300分才能参加后面的面试和办理入职手续,对于不常刷算法的码农来说难度还挺大。笔者准备了有一个多礼拜,刷了3-5天的题后于是参加了一场机考,在此之前笔者已经考过两次了,那两次连第一道题都没有完整地做处理,而且第一道题就花了很长时间,以至于后面的题目都没时间做了。

这次参加机考依然没过,但是第一道题却完整地做出来了拿了100分,可是却花了我一个半小时才做出来,后面第二、第三道题却只剩60分钟了,第二道题没想到也有难度,自己写出的代码只通过1/8的测试用例拿了12.5分,第三道200分的题目自己看了一下,没想到竟然非常简单,非常遗憾的却是由于自己没提前看这道题导致完全没时间去做了。这次笔者把第一道题的解答思路和详细代码记录到博客上来,一方面给自己复个盘,另一方面也希望对最近要参加此类机考的读者朋友们一个解题思路的参考。

题目描述

这次抽到的第一道机考题是:斗地主游戏中计算玩家手上可能存在的最大顺子, 该题的详细描述如下:

斗地主游戏中一副扑克由3-4-5-6-7-8-9-10-J-Q-K-A-2 各4个和两个大小王组成, 共54张牌, 输入两行牌,第一行为玩家手上的牌,第二行为所有玩家已经打出来的牌
案例一:输入下面这两行
3-3-3-4-4-5-6-6-7-8-9-10-J-Q-K-A
3-4-4-5-5-5-6-6-7-7-7-8-9-10-J-Q-K-A
输出:8-9-10-J-Q-K-A
案例二:输入下面这两行
3-3-4-4-5-5-6-6-7-7-9-10-J-Q
3-3-8-8-8-8-K-K-K-K

解题思路

1、使用一个HashMap的key和value分别存放3-4-5-6-7-8-9-10-J-Q-K-A 这 12 个牌和每张牌的总个数4;

2、先后遍历玩家手上的牌和已经打出的牌,HashMap中遍历的牌对应的key的话则其value值减1,减到0则表示对手玩家手上不会有这张牌;

3、遍历踢除玩家自己和所有人已经打出的牌后的HashMap, 找出value值不为0的key,并将其中的J、Q、K、A分别用11、12、13、14代替后组成一个新的HashSet集合,该集合中的牌即是对手玩家手上可能存在的牌的集合;

4、遍历第三步处理后的HashSet 集合中的元素并放入一个新的List集合中, 并将此集合按数字大小升序排序;

5、找出第4步处理后的List集合中所有组成5-12个连续数字的列表集合,并将该列表集合排序,长度不一样的按长度大的降序排列,长度相同列表的按第一个牌的数字大小降序排列,然后将排序后的列表集合中的下标为0的集合以"-"分隔符拼接起来,超过10的数字字符使用J-A中对应的字母替换。不过这种方式笔者发现自己用代码实现不了,于是改为使用下面这种方式;

6、将经过第4步处理后的List集合中的元素将其中数字大于11的元素替换成J、Q、K、A中对应的字母后以"-"分隔符拼接起来组成一个对手玩家手上存在的所有牌的大字符串String

7、将3-4-5-6-7-8-9-10-J-Q-K-A 12个字符按长度由大到小,牌面由大到小组成的12-5位顺子字符串(牌号之间使用"-"分隔)放到集合List2中;

8、遍经过第7步处理后的List2集合中的所有顺子字符串,并设置一个标识符初始值为false, 若遍历的顺子字符串包含在经过第6步处理后的大顺子字符串String中则标识符便为true, 打印该顺子字符串后跳出循环体,若遍历完List2集合中的所有顺子字符串后标识符仍然为false则标识对手玩家手上不存在顺子,打印出NO-CHAINS字符串。

代码实现

java 复制代码
import java.util.*;
/**
 * 三人斗地主游戏计算两位对家手上可能存在的最大的顺子
 * 一副扑克由3-4-5-6-7-8-9-10-A-J-Q-K-A-2 各4个和两个大小王组成, 共54张牌
 * 一个顺子至少由5张连续的牌组成,最小的顺子为3-4-5-6-7;最大有12张连续的牌,最大的顺子为3-4-5-6-7-8-9-10-J-Q-K-A
 * 输入两行牌,第一行为玩家手上的牌,第二行为所有玩家已经打出来的牌,如下面两行
 * 3-3-3-4-4-5-6-6-7-8-9-10-J-Q-K-A
 * 3-4-4-5-5-5-6-6-7-7-7-8-9-10-J-Q-K-A
 * 上面这种情况对家手上可能存在的最大顺子为:8-9-10-J-Q-K-A, 则输出该最大顺子
 * 下面这种情况对家手上不存在顺子则输出:NO-CHAINS
 * 3-3-4-4-5-5-6-6-7-7-9-10-J-Q
 * 3-3-8-8-8-8-K-K-K-K
 * 现在需要你根据输入的两行牌计算对家手上可能存在的最大顺子,并在屏幕上输出该最大顺子
 */
public class CardGame {

    public static void main(String[] args) {
        // 将3-A这12张牌每张作为一个key放入到一个HashMap中,对应的value值为4
        String[] cardNumsArray = new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};
        Map<String, Integer> cardNumMap = new HashMap<>();
        for(String cardNum: cardNumsArray){
            cardNumMap.put(cardNum, 4);
        }
        Scanner scanner = new Scanner(System.in);
        String line1 = scanner.nextLine().trim();
        String[] card1Nums = line1.split("-");
        // 玩家手上的牌有在cardNumMap中每有一张则减1
        for(String cardNum: card1Nums){
            if(cardNumMap.containsKey(cardNum)){
                cardNumMap.put(cardNum, cardNumMap.get(cardNum)-1);
            }
        }
        String line2 = scanner.nextLine().trim();
        String[] card2Nums = line2.split("-");
        // 所有玩家打出的的牌有在cardNumMap中每有一张也减1
        for(String cardNum: card2Nums){
            if(cardNumMap.containsKey(cardNum)){
                cardNumMap.put(cardNum, cardNumMap.get(cardNum)-1);
            }
        }
        List<String> cardNumList = new ArrayList<>();
        Set<String> keySet = cardNumMap.keySet();
        Map<String, String> charNumMap = new HashMap<>(4);
        charNumMap.put("J", "11");
        charNumMap.put("Q", "12");
        charNumMap.put("K", "13");
        charNumMap.put("A", "14");
        Set<String> cardNumSet = new HashSet<>();
        for(String cardNum: keySet){
            if(cardNumMap.get(cardNum).intValue()==0){
                continue; // 过滤掉对手玩家手上没有的牌
            }
            if(charNumMap.containsKey(cardNum)){
                // cardNum为J,Q,K,A的转成对应的数字
                cardNumSet.add(charNumMap.get(cardNum));
            }else{
                cardNumSet.add(cardNum);
            }
        }
        for(String key: cardNumSet){
            cardNumList.add(key);
        }
        if(cardNumList.size()>2){
            // 对手手上的牌按牌面数字的大小升序排序
            cardNumList.sort(Comparator.comparing(Integer::parseInt));
        }
        Map<String, String> numCharMap = new HashMap<>(4);
        numCharMap.put("11", "J");
        numCharMap.put("12", "Q");
        numCharMap.put("13", "K");
        numCharMap.put("14", "A");
        // 统计对手玩家手中的所有牌
        StringBuilder cardNumBuilder = new StringBuilder();
        for(int i=0; i<cardNumList.size();i++){
            String cardNum = cardNumList.get(i);
            if(i!=cardNumList.size()-1){
                if(Integer.parseInt(cardNum)<11){
                    cardNumBuilder.append(cardNum).append("-");
                }else{
                    cardNumBuilder.append(numCharMap.get(cardNum)).append("-");
                }
            } else {
                if(Integer.parseInt(cardNum)<11){
                    cardNumBuilder.append(cardNum);
                } else {
                    // 大于10的牌需要将其转成字母
                    cardNumBuilder.append(numCharMap.get(cardNum));
                }
            }
        }
        String cardNumChains = cardNumBuilder.toString();
        // 由3-4-5-6-7-8-9-10-J-Q-K-A组成的所有5-12位顺子集合
        List<String> propCardChains = new ArrayList<>();
        for(int i=12;i>=5;i--){
            int endIndex = 11; //符合5-12张顺子的情况下,任意多张顺子最大的顺子都是A牌在最后
            int startIndex = 12 - i;
            for(int j=0; j<=12-i;j++){
                StringBuilder builder = new StringBuilder();
                for(int k=startIndex; k<=endIndex; k++){
                    if(k!=endIndex){
                        builder.append(cardNumsArray[k]).append("-");
                    }else{
                        builder.append(cardNumsArray[k]);
                    }
                }
                propCardChains.add(builder.toString());
                endIndex--; //每一轮后顺子最大的牌向左移动一位
                startIndex--; //每一轮后顺子最小的牌也要向左移动一位
            }
        }
        boolean existFlag = false; // 是否匹配到顺子标识
        for(String propCardChain: propCardChains){
            if(cardNumChains.contains(propCardChain)){
                // 打印对手玩家手中可能存在的最大顺子
                System.out.println(propCardChain);
                existFlag = true;
                break;
            }
        }
        if(!existFlag){
            // 对手玩家手中不存在顺子
            System.out.println("NO-CHAINS");
        }
    }
}

上面的代码实现中最大的难点在于如何通过循环统计出由3-4-5-6-7-8-9-10-J-Q-K-A组成的所有5-12位顺子的集合,笔者考试的时候紧张得竟然想不出来如何通过多次遍历全部找出不来,而是转而使用暴力枚举将其添加到List集合中的, 不过也好在能组成顺子的组合数并不多,不然就算累死也弄不出来。

java 复制代码
// 由3-4-5-6-7-8-9-10-J-Q-K-A组成的所有5-12位顺子集合
 List<String> propCardChains = new ArrayList<>();
 // 12位长度的顺子1个
 propCardChains.add("3-4-5-6-7-8-9-10-J-Q-K-A");
 // 11位长度的顺子2个
 propCardChains.add("4-5-6-7-8-9-10-J-Q-K-A");
 propCardChains.add("3-4-5-6-7-8-9-10-J-Q-K");
 // 10 位长度的顺子3个
 propCardChains.add("5-6-7-8-9-10-J-Q-K-A");
 propCardChains.add("4-5-6-7-8-9-10-J-Q-K");
 propCardChains.add("3-4-5-6-7-8-9-10-J-Q");
 // 9位长度的顺子4个
 propCardChains.add("6-7-8-9-10-J-Q-K-A");
 propCardChains.add("5-6-7-8-9-10-J-Q-K");
 propCardChains.add("4-5-6-7-8-9-10-J-Q");
 propCardChains.add("3-4-5-6-7-8-9-10-J");
 // 8位长度的顺子5个
 propCardChains.add("7-8-9-10-J-Q-K-A");
 propCardChains.add("6-7-8-9-10-J-Q-K");
 propCardChains.add("5-6-7-8-9-10-J-Q");
 propCardChains.add("4-5-6-7-8-9-10-J");
 propCardChains.add("3-4-5-6-7-8-9-10");
 // 7位长度的顺子6个
 propCardChains.add("8-9-10-J-Q-K-A");
 propCardChains.add("7-8-9-10-J-Q-K");
 propCardChains.add("6-7-8-9-10-J-Q");
 propCardChains.add("5-6-7-8-9-10-J");
 propCardChains.add("4-5-6-7-8-9-10");
 propCardChains.add("3-4-5-6-7-8-9");
 // 6位长度的顺子7个
  propCardChains.add("9-10-J-Q-K-A");
  propCardChains.add("8-9-10-J-Q-K");
  propCardChains.add("7-8-9-10-J-Q");
  propCardChains.add("6-7-8-9-10-J");
  propCardChains.add("5-6-7-8-9-10");
  propCardChains.add("4-5-6-7-8-9");
  propCardChains.add("3-4-5-6-7-8");
// 5位长度的顺子8个
 propCardChains.add("10-J-Q-K-A");
 propCardChains.add("9-10-J-Q-K");
 propCardChains.add("8-9-10-J-Q");
 propCardChains.add("7-8-9-10-J");
 propCardChains.add("6-7-8-9-10");
 propCardChains.add("5-6-7-8-9");
 propCardChains.add("4-5-6-7-8");
 propCardChains.add("3-4-5-6-7");

从上面的枚举明细中我们也可以看出,5-12位任意长度的顺子的组合数位13-顺子长度,每个长度的顺子都是以A结尾的最大,以3开始的最小。这种暴力枚举其实也是很耗时间的,即时上面只有28种顺子组合,但是在考试过程中却用了笔者不少于30分钟才全部统计出来,而且这种手工枚举统计也是非常容易出现遗漏或者重复的,在考试过程中如果不是完全没有思路非常不建议用这种方式统计。

ChatGPT 解题

自己去思考并写出代码实现还是非常花时间的,那么我们借用当下最流行的chatGPT帮我们试试:

我们在谷歌浏览器中输入如下网址:<chat12.aichatos.xyz/

进入不需要购买梯子就能登录的chatGPT页面, 在对话框中输入下面的提问:

输入提示后点击对话框右边的生成响应按钮,很快可以看到chatGPT给我们生成了解题代码

以下是使用Java实现计算对家手上可能存在的最大顺子的代码:

java 复制代码
import java.util.*;

public class CardGameGPT {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 读取玩家手上的牌
        String playerCards = scanner.nextLine();
        // 读取所有用户打出的牌
        String playedCards = scanner.nextLine();
        // 玩家手中的牌字符串转数字集合
        List<Integer> playerCardList = parseCardString(playerCards);
        // 所有玩家已打出的牌符串转数字集合
        List<Integer> playedCardList = parseCardString(playedCards);
        // 对手玩家剩下的牌集合
        List<Integer> remainingCards = getRemainingCards(playerCardList, playedCardList);
       
        List<List<Integer>> sequences = getSequences(remainingCards);

        List<Integer> longestSequence = getLongestSequence(sequences);

        if (longestSequence.size() >= 5) {
            System.out.print(getCardString(longestSequence));
        } else {
            System.out.print("NO-CHAINS");
        }
    }
    
    /**
    * 字符串转数字集合
    */
    private static List<Integer> parseCardString(String cardString) {
        List<Integer> cardList = new ArrayList<>();
        String[] cards = cardString.split("-");
        // A、J、Q、K分别转成对应的数字
        for (String card : cards) {
            switch (card) {
                case "A":
                    cardList.add(1);
                    break;
                case "J":
                    cardList.add(11);
                    break;
                case "Q":
                    cardList.add(12);
                    break;
                case "K":
                    cardList.add(13);
                    break;
                default:
                    cardList.add(Integer.parseInt(card));
                    break;
            }
        }

        return cardList;
    }
    
    // 统计对手玩家手上的牌
    private static List<Integer> getRemainingCards(List<Integer> playerCards, List<Integer> playedCards) {
        List<Integer> remainingCards = new ArrayList<>(playerCards);
        remainingCards.removeAll(playedCards);
        Collections.sort(remainingCards);

        return remainingCards;
    }
    
    // 统计对手玩家手上所有的顺子组合,这个方法实现了笔者列出的解题思路中的第7步结果
    private static List<List<Integer>> getSequences(List<Integer> cards) {
        List<List<Integer>> sequences = new ArrayList<>();
        int count = 1; // 用于统计是否属于顺子的数字标识
        for (int i = 0; i < cards.size() - 1; i++) {
            if (cards.get(i + 1) - cards.get(i) == 1) {
                count++; // 后一个数减前一个数等于1则数字个数加1
            } else if (cards.get(i + 1) - cards.get(i) > 1) {
                // 后一个数减前一个数大于1标识顺子结束
                if (count >= 5) {
                    // 顺子个数大于等于5则将顺子组成的列表放入到sequences集合中
                    sequences.add(new ArrayList<>(cards.subList(i - count + 1, i + 1)));
                }
                // count值重置为1
                count = 1;
            }
        }
		// 判断是否有最后一个顺子,有则将其加入到sequences集合中
        if (count >= 5) {
            sequences.add(new ArrayList<>(cards.subList(cards.size() - count, cards.size())));
        }

        return sequences;
    }
    
    // 获取最长的顺子
    private static List<Integer> getLongestSequence(List<List<Integer>> sequences) {
        List<Integer> longestSequence = new ArrayList<>();

        for (List<Integer> sequence : sequences) {
            if (sequence.size() > longestSequence.size()) {
                longestSequence = sequence;
            }
        }
        return longestSequence;
    }
    
    // 获取最长的顺子
    private static String getCardString(List<Integer> cards) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < cards.size(); i++) {
            int card = cards.get(i);
            if (card == 1) {
                sb.append("A");
            } else if (card == 11) {
                sb.append("J");
            } else if (card == 12) {
                sb.append("Q");
            } else if (card == 13) {
                sb.append("K");
            } else {
                sb.append(card);
            }

            if (i < cards.size() - 1) {
                sb.append("-");
            }
        }

        return sb.toString();
    }
}

测试结果

首先运行CardGame类中的main方法, 然后在控制台中输入用例一中的两行输入参数

bash 复制代码
3-3-3-4-4-5-6-6-7-8-9-10-J-Q-K-A
3-4-4-5-5-5-6-6-7-7-7-8-9-10-J-Q-K-A

回车后看到控制台输出:8-9-10-J-Q-K-A

然后重新运行main函数继续输入用例二中的两行输入参数:

bash 复制代码
3-3-4-4-5-5-6-6-7-7-9-10-J-Q
3-3-8-8-8-8-K-K-K-K

回车后看到控制台输出:NO-CHAINS

然后运行 CardGameGPT类中的main方法后在控制台中输入用例一中的两行输入参数:

bash 复制代码
3-3-3-4-4-5-6-6-7-8-9-10-J-Q-K-A
3-4-4-5-5-5-6-6-7-7-7-8-9-10-J-Q-K-A

结果输出:NO-CHAINS

说明chatGPT生成的代码有bug,需要我们手动修改,修改后的代码如下:

java 复制代码
import java.util.*;

public class CardGameGPT {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String playerCards = scanner.nextLine();
        String playedCards = scanner.nextLine();
        List<Integer> playerCardList = parseCardString(playerCards);
        List<Integer> playedCardList = parseCardString(playedCards);
        List<Integer> remainingCards = getRemainingCards(playerCardList, playedCardList);
        List<List<Integer>> sequences = getSequences(remainingCards);
        List<Integer> longestSequence = getLongestSequence(sequences);
        if (longestSequence.size() >= 5) {
            System.out.print(getCardString(longestSequence));
        } else {
            System.out.print("NO-CHAINS");
        }
    }

    private static List<Integer> parseCardString(String cardString) {
        List<Integer> cardList = new ArrayList<>();
        String[] cards = cardString.split("-");
        for (String card : cards) {
            switch (card) {
                case "A":
                    cardList.add(14);
                    break;
                case "J":
                    cardList.add(11);
                    break;
                case "Q":
                    cardList.add(12);
                    break;
                case "K":
                    cardList.add(13);
                    break;
                default:
                    cardList.add(Integer.parseInt(card));
                    break;
            }
        }
        return cardList;
    }
    
    // 统计对手玩家手上的牌
    private static List<Integer> getRemainingCards(List<Integer> playerCards, List<Integer> playedCards) {
        List<Integer> remainingCards = new ArrayList<>();
        Map<String, Integer> carNumMap = new HashMap<>(12);
        String[] cardNumArray = new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"};
        for(String cardNum: cardNumArray){
            carNumMap.put(cardNum, 4);
        }
        for(Integer cardNum: playerCards){
            String key = String.valueOf(cardNum);
            if(carNumMap.containsKey(key)){
                carNumMap.put(key, carNumMap.get(key)-1);
            }
        }
        for(Integer cardNum: playedCards){
            String key = String.valueOf(cardNum);
            if(carNumMap.containsKey(key)){
                carNumMap.put(key, carNumMap.get(key)-1);
            }
        }
        Set<String> keySet = carNumMap.keySet();
        for(String key: keySet){
            if(carNumMap.get(key)>0){
                remainingCards.add(Integer.valueOf(key));
            }
        }
        Collections.sort(remainingCards);
        return remainingCards;
    }
    
    // 统计对手玩家手上所有的顺子组合
    private static List<List<Integer>> getSequences(List<Integer> cards) {
        List<List<Integer>> sequences = new ArrayList<>();
        int count = 1;
        for (int i = 0; i < cards.size() - 1; i++) {
            if (cards.get(i + 1) - cards.get(i) == 1) {
                count++;
            } else if (cards.get(i + 1) - cards.get(i) > 1) {
                if (count >= 5) {
                    sequences.add(new ArrayList<>(cards.subList(i - count + 1, i + 1)));
                }
                count = 1;
            }
        }

        if (count >= 5) {
            sequences.add(new ArrayList<>(cards.subList(cards.size() - count, cards.size())));
        }

        return sequences;
    }
    
    // 获取最长最大的顺子
    private static List<Integer> getLongestSequence(List<List<Integer>> sequences) {
        if(sequences.size()==0){
            // 没有顺子返回空数组
            return new ArrayList<>();
        } else if(sequences.size()==1){
            // 只有一个顺子直接返回下标为0的顺子
            return sequences.get(0);
        } else {
            sequences.sort((list1, list2)->{
                if(list1.size()!=list2.size()){
                    // 长度不同,长度大的排在前面
                    return list2.size() - list1.size();
                } else {
                    // 长度相同比较第一牌的大小
                    return list2.get(0) - list1.get(0);
                }
            });
            return sequences.get(0);
        }

    }
    
    private static String getCardString(List<Integer> cards) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < cards.size(); i++) {
            int card = cards.get(i);
            if (card == 14) {
                sb.append("A");
            } else if (card == 11) {
                sb.append("J");
            } else if (card == 12) {
                sb.append("Q");
            } else if (card == 13) {
                sb.append("K");
            } else {
                sb.append(card);
            }
            if (i < cards.size() - 1) {
                sb.append("-");
            }
        }
        return sb.toString();
    }
}

重新运行 CardGameGPT类中的main方法后在控制台中输入用例一中的两行输入参数:

bash 复制代码
3-3-3-4-4-5-6-6-7-8-9-10-J-Q-K-A
3-4-4-5-5-5-6-6-7-7-7-8-9-10-J-Q-K-A

输出:8-9-10-J-Q-K-A

再次运行 CardGameGPT类中的main方法后在控制台中输入用例二中的两行输入参数:

bash 复制代码
3-3-4-4-5-5-6-6-7-7-9-10-J-Q
3-3-8-8-8-8-K-K-K-K

输出:NO-CHAINS

再次运行 CardGameGPT类中的main方法后在控制台中输入用例三中的两行输入参数:

bash 复制代码
3-3-5-5-6-7-7-8-9-9-10-J-Q-K-A
3-4-5-6-7-8-8-8-9-9-10-J-Q-K-A

用例三位笔者新添加的测试用例,为了测试存在2个相同位数的数字时应该输出牌面最大的顺子

此时对手玩家手上存在两个5位顺子,分别是:3-4-5-6-7 和 10-J-Q-K-A

结果输出:10-J-Q-K-A

小结

本文主要研究了如何用Java代码解决**斗地主时根据玩家自己手中的牌和所有玩家打出的牌计算对手玩家手上可能存在的最大顺子**的算法题,主要用到了Map和List等数据结构以及集合的排序等算法,难点在于拿到对手玩家手上存在的所有牌后如何找到到可能的顺子集合, 笔者当时用了一种笨方法, 那就是枚举出3-4-5-6-7-8-9-10-J-Q-K-A中所有的 5-12位顺子集合并按长度和牌面由大到小排序。同时用对手手中的所有牌从小到大排序后按"-"分隔符连接组成一个大字符串然后遍历该顺子集合,然后遍历顺子集合,若对手玩家手中的牌组成的大字符串包含遍历的顺子,则输出该顺子。

但是后面``chatGPT提供的解题代码实现了笔者想实现却很难实现的建模,不得不说借助chatGPT可以很大地提高我们程序员的编程效率。虽然可能会存在一点小Bug, 但是一般经过我们的手动修改后程序都能正常地跑起来!所以最为一名程序员,我们还是在平时的工作和学习中尽可能地把chatGPT用起来吧!

现在还年青(30岁之前)想要进互联网大厂的同学可以去牛客网 或者利扣 网 上多刷一刷算法题,用代码实现解题的过程也是一个数据建模的过程,算法思维好的同学这一道题应该也容易做出来,华为OD的很多机考题其实也是来源与LeetCode上面的算法题,也就是怎么使用Java里面的数据结构通过编码把问题给解决了。其实机考时对提交的代码还有最大时间复杂度和组大空间复杂度的要求,一般要求跑完一个测试用例耗时不超过1s,内存不超过256M。这也就要求我们不仅要会编码解题,还要学会优化解题的代码实现,使得最大时间复杂度和空间复杂度做到最小,至少要能保证在题目的要求范围内。

本文首发个人微信公众号【阿福谈Web编程】,欢迎喜欢我的文章的读者朋友们加个公众号关注,第一时间阅读笔者的原创文章,大家一起在技术精进的路上同行不孤单!

相关推荐
南北是北北10 分钟前
JetPack WorkManager
面试
Swift社区11 分钟前
从 0 到 1 构建一个完整的 AGUI 前端项目的流程在 ESP32 上运行
前端·算法·职场和发展
RTC老炮15 分钟前
webrtc弱网-BitrateEstimator类源码分析与算法原理
网络·人工智能·算法·机器学习·webrtc
程序员烧烤19 分钟前
【leetcode刷题007】leetcode116、117
算法·leetcode
uhakadotcom1 小时前
在chrome浏览器插件之中,options.html和options.js常用来做什么事情
前端·javascript·面试
想想就想想1 小时前
线程池执行流程详解
面试
ghie90901 小时前
基于libsvm的支持向量机在MATLAB中的实现
算法·支持向量机·matlab
程序员清风2 小时前
Dubbo RPCContext存储一些通用数据,这个用手动清除吗?
java·后端·面试
南北是北北2 小时前
JetPack ViewBinding
面试
南北是北北3 小时前
jetpack ViewModel
面试