华为OD机试 2024E卷题库疯狂收录中,刷题点这里
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
斗地主起源于湖北十堰房县,据说是一位叫吴修全的年轻人根据当地流行的扑克玩法”跑得快”改编的,如今已风靡整个中国,并流行于互联网上。
牌型:单顺,又称顺子,最少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
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 |
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
9-10-J-Q-K-A
def main():
# 获取输入:当前手中的牌 + 已经出过的牌,并合并
my_pokers = input().strip()
already_pokers = input().strip()
merge_pokers = my_pokers + "-" + already_pokers
merge_pokers = merge_pokers.split("-")
# 为方便后续判断顺子,将JQKA转为int,reverse_map供后续打印顺子使用
char2int = {'J': 11, 'Q': 12, 'K': 13, 'A': 14}
reverse_map = {v: k for k, v in char2int.items()}
# 定义数组表示对手的牌,遍历前面合并牌数组(当前手中的牌 + 已经出过的牌),每遍历到一张牌,对手的牌对应的数组元素 - 1
# 注意: 数组长度由来:顺子有效的牌为3-14,所以长度为14 - 3 + 1
# 注意:为什么-3:有效的顺子牌从3开始,而数组下标需要从0开始
their_pokers = [0] * (14 - 3 + 1)
for poker in merge_pokers:
if len(poker) > 1: # 10
their_pokers[int(poker) - 3] -= 1
elif poker in char2int: # JQKA
their_pokers[char2int[poker] - 3] -= 1
elif poker not in ['2', 'B', 'C']:
their_pokers[int(poker) - 3] -= 1
# 动态规划获取最长的顺子,当前牌的顺子长度只与前一个牌的顺子长度和当前牌是否可用有关
prev = 1 if their_pokers[0] > -4 else 0
max_len = float('-inf')
current = 0
start = 1
for i in range(1, len(their_pokers)):
if their_pokers[i] > -4: # 有剩余牌时,拼接顺子
current = prev + 1
if current > max_len:
max_len = current
start = i + 3 - max_len + 1 # 注意这里+3,是由于数组下标和扑克牌之间差了3
else: # 无剩余牌,顺子长度置为0
current = 0
prev = current
# 符合条件
if max_len >= 5:
straight = "-".join(str(reverse_map.get(poker, poker)) for poker in range(start, start + max_len))
print(straight)
else:
print("NO-CHAIN")
if __name__ == "__main__":
main()
function main() {
const readline = require('readline-sync');
// 获取输入:当前手中的牌 + 已经出过的牌,并合并
let myPokers = readline.question().trim();
let alreadyPokers = readline.question().trim();
let mergePokers = myPokers + "-" + alreadyPokers;
mergePokers = mergePokers.split("-");
// 为方便后续判断顺子,将JQKA转为int, reverseMap供后续打印顺子使用
const char2int = { 'J': 11, 'Q': 12, 'K': 13, 'A': 14 };
const reverseMap = Object.fromEntries(Object.entries(char2int).map(([k, v]) => [v, k]));
// 定义数组表示对手的牌
const theirPokers = new Array(14 - 3 + 1).fill(0);
mergePokers.forEach(poker => {
if (poker.length > 1) { // 10
theirPokers[parseInt(poker) - 3]--;
} else if (char2int.hasOwnProperty(poker)) { //JQKA
theirPokers[char2int[poker] - 3]--;
} else if (poker !== '2' && poker !== 'B' && poker !== 'C') {
theirPokers[parseInt(poker) - 3]--;
}
});
// 动态规划获取最长的顺子,当前牌的顺子长度只与前一个牌的顺子长度和当前牌是否可用有关
let prev = theirPokers[0] > -4 ? 1 : 0;
let current = 0;
let max = -Infinity;
let start = 1;
for (let i = 1; i < theirPokers.length; i++) {
if (theirPokers[i] > -4) {
current = prev + 1;
if (current > max) {
max = current;
start = i + 3 - max + 1; // 注意这里+3,是由于数组下标和扑克牌之间差了3
}
} else {
current = 0;
}
prev = current;
}
// 符合条件
if (max >= 5) {
const straight = Array.from({ length: max }, (_, i) => {
const poker = start + i;
return poker > 10 ? reverseMap[poker] : poker;
}).join('-');
console.log(straight);
} else {
console.log("NO-CHAIN");
}
}
// 执行主函数
main();
#include
#include
#include
#define MAX_LEN 100
// 字符转换为整数映射
int char2int(char c) {
switch (c) {
case 'J': return 11;
case 'Q': return 12;
case 'K': return 13;
case 'A': return 14;
default: return c - '0';
}
}
// 整数转换为字符映射
char int2char(int n) {
switch (n) {
case 11: return 'J';
case 12: return 'Q';
case 13: return 'K';
case 14: return 'A';
default: return n + '0';
}
}
int main() {
char myPokers[MAX_LEN];
char alreadyPokers[MAX_LEN];
// 获取输入:当前手中的牌 + 已经出过的牌,并合并
scanf("%s", myPokers);
scanf("%s", alreadyPokers);
char mergePokers[MAX_LEN * 2];
snprintf(mergePokers, sizeof(mergePokers), "%s-%s", myPokers, alreadyPokers);
int theirPokers[14 - 3 + 1] = {0}; // 记录对手的牌
char *token = strtok(mergePokers, "-");
while (token != NULL) {
if (strlen(token) > 1) {
theirPokers[atoi(token) - 3]--;
} else if (token[0] != '2' && token[0] != 'B' && token[0] != 'C') {
int value = char2int(token[0]);
theirPokers[value - 3]--;
}
token = strtok(NULL, "-");
}
// 动态规划获取最长的顺子
int prev = theirPokers[0] > -4 ? 1 : 0;
int current = 0;
int max = -1;
int start = 1;
for (int i = 1; i < sizeof(theirPokers) / sizeof(theirPokers[0]); i++) {
if (theirPokers[i] > -4) {
current = prev + 1;
if (current > max) {
max = current;
start = i + 3 - max + 1;
}
} else {
current = 0;
}
prev = current;
}
// 符合条件
if (max >= 5) {
for (int i = 0; i < max; i++) {
int card = start + i;
if (card > 10) {
printf("%c", int2char(card));
} else {
printf("%d", card);
}
if (i < max - 1) {
printf("-");
}
}
printf("\n");
} else {
printf("NO-CHAIN\n");
}
return 0;
}
#include
#include
#include
#include
#include
using namespace std;
// 字符转换为整数映射
int char2int(char c) {
switch (c) {
case 'J': return 11;
case 'Q': return 12;
case 'K': return 13;
case 'A': return 14;
default: return c - '0';
}
}
// 整数转换为字符映射
char int2char(int n) {
switch (n) {
case 11: return 'J';
case 12: return 'Q';
case 13: return 'K';
case 14: return 'A';
default: return n + '0';
}
}
int main() {
string myPokers, alreadyPokers;
// 获取输入:当前手中的牌 + 已经出过的牌,并合并
cin >> myPokers >> alreadyPokers;
string mergePokers = myPokers + "-" + alreadyPokers;
int theirPokers[14 - 3 + 1] = {0}; // 记录对手的牌
char *token = strtok(&mergePokers[0], "-");
while (token != NULL) {
if (strlen(token) > 1) {
theirPokers[atoi(token) - 3]--;
} else if (token[0] != '2' && token[0] != 'B' && token[0] != 'C') {
int value = char2int(token[0]);
theirPokers[value - 3]--;
}
token = strtok(NULL, "-");
}
// 动态规划获取最长的顺子
int prev = theirPokers[0] > -4 ? 1 : 0;
int current = 0;
int max = -1;
int start = 1;
for (int i = 1; i < sizeof(theirPokers) / sizeof(theirPokers[0]); i++) {
if (theirPokers[i] > -4) {
current = prev + 1;
if (current > max) {
max = current;
start = i + 3 - max + 1;
}
} else {
current = 0;
}
prev = current;
}
// 符合条件
if (max >= 5) {
vector<string> straight;
for (int i = 0; i < max; i++) {
int card = start + i;
if (card > 10) {
straight.push_back(string(1, int2char(card)));
} else {
straight.push_back(to_string(card));
}
}
for (size_t i = 0; i < straight.size(); i++) {
cout << straight[i];
if (i < straight.size() - 1) {
cout << "-";
}
}
cout << endl;
} else {
cout << "NO-CHAIN" << endl;
}
return 0;
}
下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。