2025 B卷 100分 題型
本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式;
并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析;
本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分享》
華為OD機試真題《斗地主之順子》:
文章快捷目錄
題目描述及說明
Java
python
JavaScript
C
GO
更多內容
題目名稱:斗地主之順子
- 知識點:字符串處理、排序算法、邏輯判斷
- 時間限制:1秒
- 空間限制:256MB
- 限定語言:不限
題目描述
在斗地主撲克牌游戲中,撲克牌由小到大的順序為:3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A, 2。玩家可以出的牌型包括單張、對子、順子、飛機、炸彈等。
順子的規則:
- 由至少5張連續遞增的牌組成(例如:{3,4,5,6,7}或{3,4,5,…,K,A})。
- 不能包含2(如{J,Q,K,A,2}無效)。
- 不允許非連續或重復牌(如{3,4,5,6,8}無效)。
輸入:
13張合法撲克牌(空格隔開,不含大小王),例如:2 9 J 2 3 4 K A 7 9 A 5 6
。
輸出:
- 若有順子,按首個牌大小升序逐行輸出(如
3 4 5 6 7
)。 - 多個順子時分行輸出(如示例2)。
- 無順子則輸出
No
。
示例:
- 輸入:
2 9 J 2 3 4 K A 7 9 A 5 6
→ 輸出:3 4 5 6 7
。 - 輸入:
2 9 J 10 3 4 K A 7 Q A 5 6
→ 輸出:3 4 5 6 7
和9 10 J Q K A
。
Java
問題分析
我們需要在斗地主游戲中找出所有可能的順子牌型。順子由至少5張連續遞增的牌組成,不能包含2,且牌不可重復。輸入為13張牌,需輸出所有可能的順子,按首個牌的大小升序排列。
解題思路
-
數據預處理:
- 將牌面轉換為數值,過濾掉2。
- 去重并排序,得到有序的數值列表。
-
尋找連續序列:
- 遍歷排序后的數值列表,找出所有長度≥5的連續遞增序列。
-
結果轉換與輸出:
- 將數值序列轉換回牌面,按起始牌升序輸出。
代碼實現
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);String[] cards = scanner.nextLine().split(" ");// 建立牌面到數值的映射(3→0,A→11,2→12但會被過濾)Map<String, Integer> cardToValue = new HashMap<>();String[] order = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"};for (int i = 0; i < order.length; i++) {cardToValue.put(order[i], i);}// 過濾掉2,并轉換為不重復的數值集合Set<Integer> valueSet = new TreeSet<>();for (String card : cards) {if (cardToValue.containsKey(card)) { // 忽略2valueSet.add(cardToValue.get(card));}}List<Integer> sortedValues = new ArrayList<>(valueSet);if (sortedValues.size() < 5) { // 無足夠牌形成順子System.out.println("No");return;}List<List<Integer>> sequences = new ArrayList<>();int start = 0; // 當前連續序列的起始索引// 遍歷數值列表,尋找連續序列for (int i = 1; i <= sortedValues.size(); i++) {if (i < sortedValues.size() && sortedValues.get(i) == sortedValues.get(i-1) + 1) {continue; // 繼續連續序列} else {int length = i - start;if (length >= 5) {List<Integer> sub = sortedValues.subList(start, i); // 截取連續序列sequences.add(new ArrayList<>(sub)); // 避免引用問題}start = i; // 重置起始索引}}// 轉換為牌面并輸出List<List<String>> result = new ArrayList<>();for (List<Integer> seq : sequences) {List<String> sequence = new ArrayList<>();for (int val : seq) {sequence.add(order[val]);}result.add(sequence);}if (result.isEmpty()) {System.out.println("No");} else {for (List<String> seq : result) {System.out.println(String.join(" ", seq));}}}
}
代碼詳細解析
-
輸入處理:
- 使用
Scanner
讀取輸入并分割為牌面數組。
- 使用
-
牌面到數值的映射:
- 使用數組
order
定義牌面順序,建立cardToValue
映射。
- 使用數組
-
過濾與去重:
- 遍歷輸入的牌,過濾掉2,并將牌面轉換為數值存入
TreeSet
(自動排序并去重)。
- 遍歷輸入的牌,過濾掉2,并將牌面轉換為數值存入
-
尋找連續序列:
- 遍歷排序后的數值列表,通過比較相鄰數值判斷是否連續。
- 發現不連續時,若當前序列長度≥5,則記錄該序列。
-
結果轉換與輸出:
- 將數值序列轉換為對應的牌面,按順序輸出。
示例測試
示例1:
輸入:2 9 J 2 3 4 K A 7 9 A 5 6
輸出:
3 4 5 6 7
解析:數值序列0,1,2,3,4
對應牌面3-7。
示例2:
輸入:2 9 J 10 3 4 K A 7 Q A 5 6
輸出:
3 4 5 6 7
9 10 J Q K A
解析:兩個連續序列0-4
(3-7)和6-11
(9-A)。
示例3:
輸入:2 2 2 2 2 2 2 2 2 2 2 2 2
輸出:
No
解析:所有牌都是2,無法組成順子。
綜合分析
-
時間復雜度:
- 預處理:O(n),其中n為輸入牌數。
- 尋找連續序列:O(m),m為去重后的牌數。
-
空間復雜度:
- 使用
TreeSet
和列表存儲數值,空間復雜度為O(m)。
- 使用
-
正確性:
- 通過去重和排序確保每個順子唯一且連續,遍歷過程準確捕捉所有可能序列。
-
適用性:
- 處理任意合法輸入,包括重復牌和復雜分布,確保結果正確。
python
問題分析
我們需要在斗地主游戲中找出所有可能的順子牌型。順子由至少5張連續遞增的牌組成,不能包含2,且牌不可重復。輸入為13張牌,需輸出所有可能的順子,按首個牌的大小升序排列。
解題思路
-
數據預處理:
- 將牌面轉換為數值,過濾掉2。
- 去重并排序,得到有序的數值列表。
-
尋找連續序列:
- 遍歷排序后的數值列表,找出所有長度≥5的連續遞增序列。
-
結果轉換與輸出:
- 將數值序列轉換回牌面,按起始牌升序輸出。
代碼實現
def main():# 讀取輸入并分割成牌列表input_cards = input().split()# 定義牌面順序映射:3->0, 4->1,..., A->11,2被過濾card_order = ["3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]card_value = {card: idx for idx, card in enumerate(card_order)}# 過濾2并將牌轉換為數值,去重后排序values = []seen = set()for card in input_cards:if card in card_value: # 過濾掉2val = card_value[card]if val not in seen:seen.add(val)values.append(val)values.sort()if len(values) < 5:print("No")return# 尋找所有連續序列sequences =