华为OD机试 - 最长的顺子 - 动态规划(Python/JS/C/C++ 新系统 200分)
华为OD机试 双机位C卷题库疯狂收录中刷题点这里专栏导读本专栏收录于《华为OD机试真题Python/JS/C/C》。刷的越多抽中的概率越大私信哪吒备注华为OD加入华为OD刷题交流群每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景发现新题目随时更新。一、题目描述斗地主起源于湖北十堰房县据说是一位叫吴修全的年轻人根据当地流行的扑克玩法”跑得快”改编的如今已风靡整个中国并流行于互联网上。牌型:单顺又称顺子最少5张牌最多12张牌(3…A)不能有2也不能有大小王不计花色。例:3-4-5-6-7-87-8-9-10-J-Q3-4-5-6-7-8-9-10-J-Q-K-A可用的牌345678910JQKA2B(小王)C(大王)每种牌除大小王外有四种花色(共有13x42张牌)。1、输入手上有的牌已经出过的牌(包括对手出的和自己出的牌)2、输出对手可能构成的最长的顺子(如果有相同长度的顺子输出牌面最大的那一个)如果无法构成顺子则输出NO-CHAIN二、输入描述输入的第一行为当前手中的牌输入的第二行为已经出过的牌三、输出描述最长的顺子输入输出说明3-3-3-3-4-4-5-5-6-7-8-9-10-J-Q-K-AA-4-5-6-7-8-8-89-10-J-Q-K-A四、解题思路定义jqkaMap进行JQKA的映射转换便于排序第一行输入当前手中的牌第二行输入已经出过的牌定义集合list存储当前手中的牌 已经出过的牌定义map存储对手的牌全部牌 - 当前手中的牌 - 已经出过的牌key3-Avalue每张牌的数量获取最大的龙定义集合dragonList存储符合要求的最大的龙map倒序遍历获取符合要求的最大的龙有剩余牌时拼接龙当没有牌时表示能获取到的最大的龙如果获取的龙符合斗地主要求则直接返回否则清空dragonList重新计算如果能获取到的最大的龙不符合斗地主要求直接返回NO-CHAIN按指定格式输出。五、测试用例1、输入3-3-4-4-5-A-5-6-2-8-3-9-10-Q-7-K-J-10-BA-4-5-8-8-10-C-6-7-82、输出9-10-J-Q-K-A3、说明拼接两个字符串排除掉不能成龙的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]获取对手的牌{31, 41, 51, 62, 72, 80, 93, 101, 113, 123, 133, 142}获取对手的牌能组成的最大的龙[14, 13, 12, 11, 10, 9]数值映射转换9-10-J-Q-K-A。六、Python算法源码defmain():# 获取输入当前手中的牌 已经出过的牌并合并my_pokersinput().strip()already_pokersinput().strip()merge_pokersmy_pokers-already_pokers merge_pokersmerge_pokers.split(-)# 为方便后续判断顺子将JQKA转为intreverse_map供后续打印顺子使用char2int{J:11,Q:12,K:13,A:14}reverse_map{v:kfork,vinchar2int.items()}# 定义数组表示对手的牌遍历前面合并牌数组当前手中的牌 已经出过的牌每遍历到一张牌对手的牌对应的数组元素 - 1# 注意: 数组长度由来顺子有效的牌为3-14所以长度为14 - 3 1# 注意为什么-3有效的顺子牌从3开始而数组下标需要从0开始their_pokers[0]*(14-31)forpokerinmerge_pokers:iflen(poker)1:# 10their_pokers[int(poker)-3]-1elifpokerinchar2int:# JQKAtheir_pokers[char2int[poker]-3]-1elifpokernotin[2,B,C]:their_pokers[int(poker)-3]-1# 动态规划获取最长的顺子当前牌的顺子长度只与前一个牌的顺子长度和当前牌是否可用有关prev1iftheir_pokers[0]-4else0max_lenfloat(-inf)current0start1foriinrange(1,len(their_pokers)):iftheir_pokers[i]-4:# 有剩余牌时拼接顺子currentprev1ifcurrentmax_len:max_lencurrent starti3-max_len1# 注意这里3是由于数组下标和扑克牌之间差了3else:# 无剩余牌顺子长度置为0current0prevcurrent# 符合条件ifmax_len5:straight-.join(str(reverse_map.get(poker,poker))forpokerinrange(start,startmax_len))print(straight)else:print(NO-CHAIN)if__name____main__:main()七、JavaScript算法源码functionmain(){constreadlinerequire(readline-sync);// 获取输入当前手中的牌 已经出过的牌并合并letmyPokersreadline.question().trim();letalreadyPokersreadline.question().trim();letmergePokersmyPokers-alreadyPokers;mergePokersmergePokers.split(-);// 为方便后续判断顺子将JQKA转为int, reverseMap供后续打印顺子使用constchar2int{J:11,Q:12,K:13,A:14};constreverseMapObject.fromEntries(Object.entries(char2int).map(([k,v])[v,k]));// 定义数组表示对手的牌consttheirPokersnewArray(14-31).fill(0);mergePokers.forEach(poker{if(poker.length1){// 10theirPokers[parseInt(poker)-3]--;}elseif(char2int.hasOwnProperty(poker)){//JQKAtheirPokers[char2int[poker]-3]--;}elseif(poker!2poker!Bpoker!C){theirPokers[parseInt(poker)-3]--;}});// 动态规划获取最长的顺子当前牌的顺子长度只与前一个牌的顺子长度和当前牌是否可用有关letprevtheirPokers[0]-4?1:0;letcurrent0;letmax-Infinity;letstart1;for(leti1;itheirPokers.length;i){if(theirPokers[i]-4){currentprev1;if(currentmax){maxcurrent;starti3-max1;// 注意这里3是由于数组下标和扑克牌之间差了3}}else{current0;}prevcurrent;}// 符合条件if(max5){conststraightArray.from({length:max},(_,i){constpokerstarti;returnpoker10?reverseMap[poker]:poker;}).join(-);console.log(straight);}else{console.log(NO-CHAIN);}}// 执行主函数main();八、C算法源码#includestdio.h#includestdlib.h#includestring.h#defineMAX_LEN100// 字符转换为整数映射intchar2int(charc){switch(c){caseJ:return11;caseQ:return12;caseK:return13;caseA:return14;default:returnc-0;}}// 整数转换为字符映射charint2char(intn){switch(n){case11:returnJ;case12:returnQ;case13:returnK;case14:returnA;default:returnn0;}}intmain(){charmyPokers[MAX_LEN];charalreadyPokers[MAX_LEN];// 获取输入当前手中的牌 已经出过的牌并合并scanf(%s,myPokers);scanf(%s,alreadyPokers);charmergePokers[MAX_LEN*2];snprintf(mergePokers,sizeof(mergePokers),%s-%s,myPokers,alreadyPokers);inttheirPokers[14-31]{0};// 记录对手的牌char*tokenstrtok(mergePokers,-);while(token!NULL){if(strlen(token)1){theirPokers[atoi(token)-3]--;}elseif(token[0]!2token[0]!Btoken[0]!C){intvaluechar2int(token[0]);theirPokers[value-3]--;}tokenstrtok(NULL,-);}// 动态规划获取最长的顺子intprevtheirPokers[0]-4?1:0;intcurrent0;intmax-1;intstart1;for(inti1;isizeof(theirPokers)/sizeof(theirPokers[0]);i){if(theirPokers[i]-4){currentprev1;if(currentmax){maxcurrent;starti3-max1;}}else{current0;}prevcurrent;}// 符合条件if(max5){for(inti0;imax;i){intcardstarti;if(card10){printf(%c,int2char(card));}else{printf(%d,card);}if(imax-1){printf(-);}}printf(\n);}else{printf(NO-CHAIN\n);}return0;}九、C算法源码#includeiostream#includestring#includecstring#includemap#includevectorusingnamespacestd;// 字符转换为整数映射intchar2int(charc){switch(c){caseJ:return11;caseQ:return12;caseK:return13;caseA:return14;default:returnc-0;}}// 整数转换为字符映射charint2char(intn){switch(n){case11:returnJ;case12:returnQ;case13:returnK;case14:returnA;default:returnn0;}}intmain(){string myPokers,alreadyPokers;// 获取输入当前手中的牌 已经出过的牌并合并cinmyPokersalreadyPokers;string mergePokersmyPokers-alreadyPokers;inttheirPokers[14-31]{0};// 记录对手的牌char*tokenstrtok(mergePokers[0],-);while(token!NULL){if(strlen(token)1){theirPokers[atoi(token)-3]--;}elseif(token[0]!2token[0]!Btoken[0]!C){intvaluechar2int(token[0]);theirPokers[value-3]--;}tokenstrtok(NULL,-);}// 动态规划获取最长的顺子intprevtheirPokers[0]-4?1:0;intcurrent0;intmax-1;intstart1;for(inti1;isizeof(theirPokers)/sizeof(theirPokers[0]);i){if(theirPokers[i]-4){currentprev1;if(currentmax){maxcurrent;starti3-max1;}}else{current0;}prevcurrent;}// 符合条件if(max5){vectorstringstraight;for(inti0;imax;i){intcardstarti;if(card10){straight.push_back(string(1,int2char(card)));}else{straight.push_back(to_string(card));}}for(size_t i0;istraight.size();i){coutstraight[i];if(istraight.size()-1){cout-;}}coutendl;}else{coutNO-CHAINendl;}return0;}下一篇华为OD机试真题 - 简易内存池Python/JS/C/C 新系统 200分本文收录于华为OD机试真题Python/JS/C/C刷的越多抽中的概率越大私信哪吒备注华为OD加入华为OD刷题交流群每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景发现新题目随时更新。