欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > 【解题报告】面试算法题:判断同花顺#模拟#哈希表#二面

【解题报告】面试算法题:判断同花顺#模拟#哈希表#二面

2024/10/24 8:52:55 来源:https://blog.csdn.net/sinat_34524528/article/details/143198389  浏览:    关键词:【解题报告】面试算法题:判断同花顺#模拟#哈希表#二面

题目:
N(5<=N<=52)张扑克牌 判断是否存在同花顺
花色:S H C D
点数:A 2 3 4 5 6 7 8 9 10 J Q K
方片A:“DA”
梅花10:“C10”
同花顺

  1. 5张扑克牌
  2. 花色相同
  3. 连成顺子
    A 2 3 4 5
    2 3 4 5 6

    9 10 J Q K
    10 J Q K A

请编写程序,解决上面的问题。

Java语言题解

public class Card {public static void main(String[] args) {boolean b =  isStraightFlush(new String[]{"DA", "D2", "D3", "D4", "D5"}); //tSystem.out.println(b? "是":"否");System.out.println(isStraightFlush(new String[]{"DA", "D3", "D2", "D4", "D5"})); // trueSystem.out.println(isStraightFlush(new String[]{"SJ", "SK", "SA", "SQ", "S10"})); //TRUESystem.out.println(isStraightFlush(new String[]{"SJ", "SK", "SA", "SQ", "S2"})); //FALSESystem.out.println(isStraightFlush(new String[]{"DJ", "SK", "SA", "SQ", "S10"})); //FALSE}public static boolean isStraightFlush(String[] cards) {if (cards.length < 5) {return false;}// 花色映射Map<Character, Integer> suitMap = new HashMap<>();suitMap.put('S', 0);suitMap.put('H', 1);suitMap.put('C', 2);suitMap.put('D', 3);// 点数映射Map<String, Integer> rankMap = new HashMap<>();rankMap.put("A", 1);rankMap.put("2", 2);rankMap.put("3", 3);rankMap.put("4", 4);rankMap.put("5", 5);rankMap.put("6", 6);rankMap.put("7", 7);rankMap.put("8", 8);rankMap.put("9", 9);rankMap.put("10", 10);rankMap.put("J", 11);rankMap.put("Q", 12);rankMap.put("K", 13);// 将扑克牌按花色和点数排序int[][] sortedCards = new int[cards.length][2];for (int i = 0; i < cards.length; i++) {sortedCards[i][0] = suitMap.get(cards[i].charAt(0));sortedCards[i][1] = rankMap.get(cards[i].substring(1));}Arrays.sort(sortedCards, (a, b) -> a[0] == b[0]? a[1] - b[1] : a[0] - b[0]);// 检查是否为同花顺for (int i = 0; i < cards.length - 4; i++) {if (sortedCards[i][0] == sortedCards[i + 4][0] && // 花色相同sortedCards[i + 4][1] - sortedCards[i][1] == 4) { // 点数连续return true;}}// 检查A-5的顺子if (sortedCards[0][1] == 1 && // AsortedCards[cards.length - 1][1] == 13 && // KsortedCards[cards.length - 2][1] == 12 && // QsortedCards[cards.length - 3][1] == 11 && // JsortedCards[cards.length - 4][1] == 10) { // 10return true;}return false;}
}

解读


当前代码是Java语言编写的,它实现了一个扑克牌游戏中判断是否存在同花顺的功能。以下是对当前代码的解释:
代码功能:
这段代码的主要功能是判断给定的一组扑克牌是否构成同花顺。同花顺是指五张花色相同且点数连续的牌。
代码逻辑:
首先,代码检查输入的扑克牌数组是否至少有5张牌,如果不足5张,则直接返回false,因为同花顺至少需要5张牌。
然后,代码创建了两个映射(suitMap和rankMap),分别用于将花色字符和点数字符映射到整数,以便后续的比较和排序。
接下来,代码将输入的扑克牌字符串数组转换为一个二维整数数组sortedCards,其中第一维表示花色,第二维表示点数。
使用Arrays.sort方法对sortedCards进行排序,排序的规则是先按花色排序,然后在花色相同的情况下按点数排序。这里使用了一个Lambda表达式作为排序的比较器。
排序完成后,代码开始检查是否存在同花顺。它通过遍历排序后的数组,检查是否有连续的5张牌花色相同且点数连续。如果找到这样的组合,则返回true,表示存在同花顺。
此外,代码还特别处理了A-5的顺子情况,因为在扑克牌中,A可以作为点数1或者14(在A-5的顺子中作为14)。如果数组中包含A且同时包含KQJ10,则也认为是同花顺,返回true。
如果没有找到符合条件的同花顺组合,则最终返回false。
代码优化:
代码已经相当简洁,但可以考虑添加一些注释来解释关键部分的逻辑,以提高代码的可读性。
此外,可以考虑将花色和点数的映射提取到常量类中,以便于管理和维护。
代码示例:
代码中已经包含了一些示例调用,展示了如何使用isStraightFlush方法来判断不同的扑克牌组合是否构成同花顺。
总结来说,这段代码通过映射、排序和遍历的方式,有效地判断了一组扑克牌是否构成同花顺,并且考虑了A-5顺子的特殊情况。特别地,遍历检查有一个 -4 ,是因为输入b可能是5-52,并不是只判断5张。所以需要五张五张地判断。在循环结束时,最后判断晚五张,i<len-4 ,此时就遍历完了。

Arrays.sort(sortedCards, (a, b) -> a[0] == b[0]? a[1] - b[1] : a[0] - b[0]); 这个语句是什么意思?


## Arrays.sort(sortedCards, (a, b) -> a[0] == b[0]? a[1] - b[1] : a[0] - b[0]); 这个语句是什么意思?
Arrays.sort(sortedCards, (a, b) -> a[0] == b[0]? a[1] - b[1] : a[0] - b[0]); 这行代码的作用是对一个二维整数数组 sortedCards 进行排序。这个二维数组中的每个元素都是一个包含两个整数的数组,第一个整数表示花色,第二个整数表示点数。
排序的规则是:首先按照花色进行排序,如果花色相同,则按照点数进行排序。这里使用了 Java 8 引入的 Lambda 表达式来定义排序的比较器。
具体来说,(a, b) -> a[0] == b[0]? a[1] - b[1] : a[0] - b[0] 是一个 Lambda 表达式,它实现了 Comparator 接口的 compare 方法。这个 Lambda 表达式接收两个参数 a 和 b,分别代表要比较的两个元素。
表达式的逻辑如下:
如果 a[0](花色)等于 b[0](花色),则比较 a[1](点数)和 b[1](点数),返回它们的差值。
如果 a[0](花色)不等于 b[0](花色),则比较 a[0](花色)和 b[0](花色),返回它们的差值。
这样,Arrays.sort 方法就会根据这个比较器的规则对 sortedCards 数组进行排序。排序后的数组中,花色相同的牌会按照点数从小到大排列,而花色不同的牌则会按照花色的顺序排列。
这个排序步骤是判断同花顺的关键,因为同花顺要求五张牌不仅花色相同,而且点数连续。通过排序,我们可以更容易地检查是否存在这样的连续点数序列。

为什么 sortedCards[i + 4][1] - sortedCards[i][1] == 4 能表示点数连续?

在扑克牌中,点数是连续的,意味着每张牌的点数比前一张牌的点数大1。因此,如果我们有五张牌,并且它们是连续的,那么第五张牌的点数应该比第一张牌的点数大4。
在你的代码中,sortedCards 是一个二维数组,其中第一维表示花色,第二维表示点数。当你检查 sortedCards[i + 4][1] - sortedCards[i][1] == 4 时,你实际上是在检查第五张牌的点数是否比第一张牌的点数大4。如果这个条件满足,那么这五张牌就是连续的。
例如,假设我们有以下五张牌:
sortedCards[i] = [0, 1] (表示花色为0,点数为1,即A)
sortedCards[i + 1] = [0, 2] (表示花色为0,点数为2,即2)
sortedCards[i + 2] = [0, 3] (表示花色为0,点数为3,即3)
sortedCards[i + 3] = [0, 4] (表示花色为0,点数为4,即4)
sortedCards[i + 4] = [0, 5] (表示花色为0,点数为5,即5)
在这个例子中,sortedCards[i + 4][1] - sortedCards[i][1] 的值为 5 - 1 = 4,这表明这五张牌的点数是连续的。
因此,sortedCards[i + 4][1] - sortedCards[i][1] == 4 是用来判断五张牌的点数是否连续的条件。如果这个条件满足,那么这五张牌就构成了一个同花顺。

为什么需要特殊处理A-5的顺子?

        // 检查A-5的顺子if (sortedCards[0][1] == 1 && // AsortedCards[cards.length - 1][1] == 13 && // KsortedCards[cards.length - 2][1] == 12 && // QsortedCards[cards.length - 3][1] == 11 && // JsortedCards[cards.length - 4][1] == 10) { // 10return true;}
这段代码是用来检查是否存在A-5的顺子,也就是最小的顺子。在扑克牌中,A可以作为点数1或者14,但是在顺子中,A通常被视为1。因此,如果我们有A-5的顺子,它的点数顺序应该是A1)、2345。
代码的逻辑如下:
sortedCards[0][1] == 1:检查第一张牌是否是A(点数为1)。
sortedCards[cards.length - 1][1] == 13:检查最后一张牌是否是K(点数为13)。
sortedCards[cards.length - 2][1] == 12:检查倒数第二张牌是否是Q(点数为12)。
sortedCards[cards.length - 3][1] == 11:检查倒数第三张牌是否是J(点数为11)。
sortedCards[cards.length - 4][1] == 10:检查倒数第四张牌是否是10(点数为10)。
如果以上所有条件都满足,那么这五张牌就构成了A-5的顺子,因此代码返回true。如果有任何一个条件不满足,那么这五张牌就不是A-5的顺子,代码不会执行return true;语句,而是继续执行后面的代码。
请注意,这段代码只检查了A-5的顺子,而没有检查其他可能的顺子,比如2-63-7等等。如果需要检查其他顺子,需要添加相应的代码

为什么需要特殊处理A-5的顺子?

在扑克牌游戏中,A(Ace)通常被视为最小的牌,其点数为1。然而,在某些情况下,A也可以被用作最大的牌,其点数为14(在一些游戏中,A可以作为1或者14使用)。在判断同花顺时,如果不特殊处理A-5的顺子,那么当A被视为14时,就无法正确识别A-5的顺子。
例如,如果我们有以下五张牌:
A(点数为12
3
4
5
这是一个顺子,因为点数是连续的。但是,如果A被视为14,那么这个顺子就不连续了,因为14之后是2,而不是1。因此,我们需要特殊处理A-5的顺子,以确保无论A被视为1还是14,都能正确识别这个顺子。
在代码中,特殊处理A-5的顺子的逻辑是:
首先检查第一张牌是否是A(点数为1)。
然后检查最后四张牌是否是K(点数为13)、Q(点数为12)、J(点数为11)和10(点数为10)。
如果以上条件都满足,那么这五张牌就构成了A-5的顺子,返回true。
这样,无论A被视为1还是14,都能正确识别A-5的顺子,从而确保同花顺的判断是准确的。

如果题目要求不允许使用 Arrays.sort排序工具类,请问改写这个程序

//在不使用 Arrays.sort 方法的情况下,我们可以使用冒泡排序来实现对二维数组的排序。以下是修改后的代码
public class CardNoSortUtil {public static void main(String[] args) {boolean b = isStraightFlush(new String[]{"DA", "D2", "D3", "D4", "D5"}); //tSystem.out.println(b? "是" : "否");System.out.println(isStraightFlush(new String[]{"DA", "D3", "D2", "D4", "D5"})); // trueSystem.out.println(isStraightFlush(new String[]{"SJ", "SK", "SA", "SQ", "S10"})); //TRUESystem.out.println(isStraightFlush(new String[]{"SJ", "SK", "SA", "SQ", "S2"})); //FALSESystem.out.println(isStraightFlush(new String[]{"DJ", "SK", "SA", "SQ", "S10"})); //FALSE}public static boolean isStraightFlush(String[] cards) {if (cards.length < 5) {return false;}// 花色映射Map<Character, Integer> suitMap = new HashMap<>();suitMap.put('S', 0);suitMap.put('H', 1);suitMap.put('C', 2);suitMap.put('D', 3);// 点数映射Map<String, Integer> rankMap = new HashMap<>();rankMap.put("A", 1);rankMap.put("2", 2);rankMap.put("3", 3);rankMap.put("4", 4);rankMap.put("5", 5);rankMap.put("6", 6);rankMap.put("7", 7);rankMap.put("8", 8);rankMap.put("9", 9);rankMap.put("10", 10);rankMap.put("J", 11);rankMap.put("Q", 12);rankMap.put("K", 13);// 将扑克牌按花色和点数排序int[][] sortedCards = new int[cards.length][2];for (int i = 0; i < cards.length; i++) {sortedCards[i][0] = suitMap.get(cards[i].charAt(0));sortedCards[i][1] = rankMap.get(cards[i].substring(1));}// 使用冒泡排序对二维数组进行排序for (int i = 0; i < sortedCards.length; i++) {for (int j = 0; j < sortedCards.length - i - 1; j++) {if (sortedCards[j][0] > sortedCards[j + 1][0] ||(sortedCards[j][0] == sortedCards[j + 1][0] && sortedCards[j][1] > sortedCards[j + 1][1])) {int[] temp = sortedCards[j];sortedCards[j] = sortedCards[j + 1];sortedCards[j + 1] = temp;}}}// 检查是否为同花顺for (int i = 0; i < cards.length - 4; i++) {if (sortedCards[i][0] == sortedCards[i + 4][0] && // 花色相同sortedCards[i + 4][1] - sortedCards[i][1] == 4) { // 点数连续return true;}}// 检查A-5的顺子if (sortedCards[0][1] == 1 && // AsortedCards[cards.length - 1][1] == 13 && // KsortedCards[cards.length - 2][1] == 12 && // QsortedCards[cards.length - 3][1] == 11 && // JsortedCards[cards.length - 4][1] == 10) { // 10return true;}return false;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com