资讯动态

华为OD机试Python刷题全攻略:题型模板与避坑实战解析

发布时间:2026/10/20 12:50:30 来源:尧图企业网站定制
简介面向华为OD机试的Python编程题解压缩包主要服务于正在备考华为在线开发者面试的候选人也可作为算法与Python应用的日常练习材料。包内收录了牛客网和CSDN平台上的系列上机题目覆盖IP地址识别、01背包动态规划、扑克牌牌型比较、素数伴侣、数字转英文、最少交换排队、供餐最小速度、顺子检测等典型场景针对性较强。文件总量为106个其中103个为.py源码脚本另有3个.txt说明文档脚本按题号命名便于快速定位题目与对照思路。压缩包体积仅59KB轻量便携适合随时下载查阅。目前已有1592人学习下载。代码中既包含完整解题实现也渗透了动态规划、字符串格式化、质数筛法、深拷贝、排序与枚举等关键Python知识点并附有若干CSDN题解脚本可作为面试冲刺阶段的参考题库与编码范例。1. 华为OD机试代码Python这份刷题资源到底解决了什么问题华为OD机试的题量和难度这几年水涨船高我在帮几个朋友做模拟面试辅导时最常被问到的问题不是“算法怎么写”而是“Python刷题到底按什么顺序来、边界条件怎么处理、代码模板能不能直接复用”。市面上散落的题解确实不少但大多数只贴一段代码不讲输入输出的坑也不说代码在机试环境里会不会超时新手照着抄完一跑就翻车。这份Python语言版的华为OD机试代码资源把题库按题型拆好每道题配了可直接运行的完整实现我拆完整体看下来它更像一份「机试生存手册」——适合正在冲刺机试的求职者也适合想系统过一遍常见题型、把Python代码模板固化下来的从业者。1. 正文里先交代清楚这是什么、能解决什么、适合谁后面再逐步拆解怎么用。2. 题解代码的正确打开方式按题型组织与模块化拆分2.1 为什么按题型刷比按题号刷效率更高拿到这份资源后我第一反应是看它的目录结构。它没有按题号平铺而是把题目分成了若干大类。这个组织方式我比较认可。实际机试的出题逻辑就是「题型驱动」的同一类题在不同场次里反复出现只是换了个业务场景的外壳。比如拓扑排序可以在任务调度题里出现也可以在依赖安装顺序题里出现核心代码几乎不变。按题型刷意味着你练的不是一道题而是一类题的通用解法。我一般会建议准备机试的人先花一个下午把题解资源里的分类目录过一遍标记出自己不熟悉的题型而不是急着从第一题开始做。这个资源的分类里字符串处理、数组与模拟、贪心、动态规划、DFS/BFS、图论、数学规律这几类基本覆盖了机试的高频范围。每道题目的代码都有注释不光是复杂逻辑处有注释输入读取部分也标了参数含义这对用Python刷题的人来说太重要了。2.2 代码模板怎么抽离成自己的工具函数这份资源里有一个很实用的特点很多题解都用了自定义的输入读取模板。机试OJ的输入格式千奇百怪有的用空格分隔有的用换行分隔有的第一行是数量第二行才是数据。如果你每道题都重新写一遍输入解析既浪费时间又容易出错。我习惯的做法是把常用输入解析封装成几个小函数放进一个单独的模板文件里每天刷题开始前先默写一遍这几个函数。# 常用输入解析模板适配机试OJ的三种典型场景 import sys def read_all_ints(): 读取全部整数适用于输入没有明确行数的情况 data sys.stdin.read().strip().split() return list(map(int, data)) def read_first_line_rest(): 第一行是数量n后续n行是n个元素 n int(sys.stdin.readline().strip()) items [sys.stdin.readline().strip() for _ in range(n)] return n, items def read_matrix(): 读取二维矩阵第一行是行数列数 m, n map(int, sys.stdin.readline().strip().split()) matrix [list(map(int, sys.stdin.readline().strip().split())) for _ in range(m)] return m, n, matrixread_all_ints适合那种输入全在一行或者多行但整体是一个序列的题比如求一组数字的最大值和最小值时用这个最省事。read_first_line_rest适合图形结构和字符串序列第一行告诉你有几个节点后面跟着每个节点的信息。read_matrix不用说了几乎所有带网格的题都用它。这三个模板我用了很久机试里百分之八九十的输入场景都能cover住。抽离成模板之后刷题时注意力只需要放在核心算法上输入解析这个环节永远不会成为你的卡点。2.3 为什么这份资源里的代码能直接用而不是只给伪代码现在网上很多题解给的是不完整的代码片段核心函数写了但主函数里怎么调用、输入怎么接进去全留给你自己猜。这份资源里的代码基本都是完整的拿到就能跑。我特意测试了几个不同题型的代码从字符串操作到图论遍历都能直接复制进OJ跑通。要做到这一点其实不容易因为机试OJ对输入输出的判定很严格多打一个空格都算错。这个资源在输出格式上也做了对齐我翻代码时看到有些题解甚至在注释里写了「注意最后要加换行」之类的提示。提示完整的可运行代码本身就是一个排错工具。当你拿到一段跑不通的代码时能快速定位是输入解析的问题还是算法逻辑的问题这个能力在考场上非常值钱。2.4 一个具体例子从题目到完整实现的拆解过程我挑一道资源里的模拟类题目来说说。题目大意是给一个字符串序列要求按某种规则排序。这种题看起来简单但排序规则里总有几个边界条件容易漏。资源里的解法先拆解了排序规则把比较的关键字提取出来然后定义了一个排序函数传入key最后再统一输出。这种写法就很Pythonic而且很适合机试——因为判题只关心输出不关心你用了什么高级技巧。# 多关键字排序的机试实现从输入到输出一步到位 import sys from functools import cmp_to_key def compare(a, b): 自定义比较器第一关键字优先第二关键字兜底 if a[0] ! b[0]: return a[0] - b[0] return a[1] - b[1] def solve(): lines sys.stdin.readline().strip() if not lines: return n int(lines) data [] for _ in range(n): parts sys.stdin.readline().strip().split() # 将两个字段分别转成不同数据类型 data.append((int(parts[0]), parts[1])) data.sort(keycmp_to_key(compare)) for item in data: print(item[0], item[1]) if __name__ __main__: solve()这段代码里要注意compare函数的返回值类型。Python的cmp_to_key要求比较器返回负数、0或正数所以用减法来实现升序是很直观的。如果你不想用cmp_to_key也可以用lambda构造多级排序的key值比如把数字取负实现降序再配合字符串排序但可读性会差不少。机试现场不建议搞太花哨的写法越直白越好因为调试时间成本太高。这个例子也展示了资源里代码的一个共性它不会为了炫技去用奇技淫巧而是选择最容易验证、最不容易写错的方式。这点对于考场上写代码非常重要。我在辅导A同学时他一开始总喜欢把排序写成一行列表推导加上复杂lambda结果每次运行出错都要想很久才能反应过来后来我让他改成这种分步骤写法思路一下就清晰了。3. 高频考点与典型题型从边界条件到输入输出格式3.1 边界条件处理机试里最容易丢分的环节机试判题不是只看算法对不对边界条件一旦没处理好一个用例不过就扣一个用例的分。我在这个资源里看到很多题解都在边界条件上下了功夫。比如数组下标越界、空输入、单元素输入、极大值输入这些场景在代码里都有对应处理。这份资源里甚至有些题解在注释里专门标注了「注意输入可能为空行」。# 边界条件防护的常见套路先判空再处理 import sys def safe_parse(): line sys.stdin.readline().strip() if not line: return 0, [] n int(line) arr [] while len(arr) n: arr.extend(map(int, sys.stdin.readline().strip().split())) return n, arr上面的代码有一个小细节值得学while len(arr) n这里。因为OJ的输入有时并不是严格地每行固定几个数用extend可以兼容多个数字在同一行的情况。很多新手以为有多少行就读多少行结果遇到不规则的换行就直接崩了。这种防御式写法虽然多两行代码但能挡住不少隐藏的输入格式坑。我在实际测试中也确实遇到过那种用readline按行读会漏数字的用例换成read_all或extend方案后就没再翻车。3.2 贪心与动态规划两类题型的代码结构对比机试里贪心和动态规划出现的频率非常高。单看代码长度贪心通常比动态规划短不少但短不代表简单。贪心题的核心难度在于证明贪心策略是正确的这个在考场上来不及严格证明更多靠经验积累。资源里把典型的贪心题归在一起我刷下来发现它们有一个共性几乎都要排序排序完之后再用一个循环去扫描。动态规划题则完全是另一种结构。资源里的动态规划解法普遍遵循「状态定义、初始化、转移方程、优化」这个步骤来写。我随便挑一道经典的背包类题目它给出的Python代码虽然不长但每一步都标注了状态变量代表什么这对于回头看代码的人来说简直太友好了。# 动态规划模板01背包问题的标准实现 import sys n, capacity map(int, sys.stdin.readline().strip().split()) weights [] values [] for _ in range(n): w, v map(int, sys.stdin.readline().strip().split()) weights.append(w) values.append(v) # dp[i]表示容量为i时能装下的最大价值 dp [0] * (capacity 1) for i in range(n): for j in range(capacity, weights[i] - 1, -1): dp[j] max(dp[j], dp[j - weights[i]] values[i]) print(dp[capacity])这段代码里有一个极其关键的细节内层循环的遍历方向必须从capacity到weights[i]递减。如果从小到大遍历同一个物品会被重复放入那就变成了完全背包而不是01背包。我见过很多人在这类题上吃亏就是因为循环顺序反了结果正确答案永远差一点。这个资源里在这类容易出现方向性错误的地方几乎都有显眼的注释提醒。这种「代码注释」的方式比单纯看讲解视频来得更直接。还有一个细节是dp数组初始化长度为capacity1这个1是因为python里下标从0开始你要能索引到capacity就必须长度是capacity1。这类小坑Python新手最容易忽略但在资源里多数题解都处理得很规范。3.3 字符串处理机试的隐形重头戏很多人以为机试就是考算法题但实际上字符串处理单独成类的题目占比很高。原因很简单业务场景里大部分输入都是字符串比如日志分析、协议解析、敏感词过滤之类的场景题。资源里对这个分类的题目收录得相当齐全。我注意到它的字符串题解大量使用了正则表达式、split、切片这些Python高效特性。但在用这些特性的同时代码里也保留了一些朴素的写法因为不是所有字符串操作都能用正则一行搞定。# 字符串解析的机试场景兼顾速度与可读性 import re def extract_key_value(line): 从形如 key:value,key2:value2 的字符串中解析出字典 result {} parts line.split(,) for part in parts: if : not in part: continue # 防御非法格式脏数据直接跳过 key, value part.split(:, 1) result[key.strip()] value.strip() return resultsplit(:, 1)这行里那个1很讲究。它表示只切第一刀如果value里本身包含冒号也不会被误切。机试里这种细小的处理往往就是区分通过和失败的临界点。如果你用split(:)不带参数遇到value里有冒号的情况就会解出多余的元素导致报错。另外continue那行的防御处理也很重要真实题目里偶尔会出现空字符串如果不做过滤直接取下标IndexError瞬间打断你的程序这个错误在OJ里通常不会给你任何额外的错误提示只显示运行错误。3.4 图论与搜索DFS、BFS的模板化写法图论题在这份资源里也是重头戏。深搜和广搜的模板其实非常固定难的是理解什么时候用深搜什么时候用广搜。我总结的经验是求最短路径、最少步骤、最少操作次数时用广搜因为广搜天然保证第一次到达目标节点时就是最短路径而遍历所有可能路径、排列组合、连通性判断时用深搜因为深搜更节省空间状态。资源里的模板基本也是按这个思路来组织代码的。# 广搜模板求从起点到终点的最短步数 from collections import deque def bfs_min_steps(grid, start, target): rows, cols len(grid), len(grid[0]) visited [[False] * cols for _ in range(rows)] queue deque() queue.append((start[0], start[1], 0)) # 第三位记录步数 visited[start[0]][start[1]] True while queue: r, c, steps queue.popleft() if (r, c) target: return steps for dr, dc in [(1, 0), (-1, 0), (0, 1), (0, -1)]: nr, nc r dr, c dc if 0 nr rows and 0 nc cols and not visited[nr][nc] and grid[nr][nc] ! 1: visited[nr][nc] True queue.append((nr, nc, steps 1)) return -1 # 不可达时返回 -1 是机试常用标记广搜模板的核心是visited数组。这个数组的作用是防止同一个节点被多次入队。如果没有visited碰上环状的图会直接死循环或者内存溢出。还有一个细节值得注意入队时就要立即标记visited而不是出队时再标记。如果出队时标记会导致同一层的多个节点重复将同一个下层节点加入队列浪费大量时间在数据规模稍大的用例中就会超时。资源里的图论代码在处理这类问题时就非常规范每一行都能看出对搜索本质的理解。我拿到这套模板之后反复练习后来做DFS时也慢慢摸清了回溯和标记状态恢复的配合。4. 避坑机试Python代码调试中常见的四类问题与排查路径4.1 输入读取卡死明明按回车了却一直读不完很多人在模拟机试时遇到过这个现象代码在本地测试怎么跑都正常一贴进OJ就变成了「运行超时」或者「输出为空」。我排查过不少这种情况根子几乎都出在输入读取方式上。如果题目说输入多行数据但没明确告诉你行数你使用for循环加sys.stdin.readline去读取固定行数一旦实际输入比预期少一行程序就停在那里等待输入自然就超时了。解决方法是优先使用read或者readlines读取全部内容然后自己切割。资源里很多题目就是用read_all再切分的方式来写的这就是为什么它的代码在OJ里不容易卡输入。4.2 递归深度爆掉Python默认递归上限比你想的低Python的默认递归深度上限只有1000层左右而机试中的DFS递归写法很容易在树形结构或链式结构里碰到这个上限。现象很有意思在小规模数据下代码完全正常一旦数据规模变大程序直接报RecursionError而且没有任何中间过程提示。解决思路很简单在代码开头手动提高递归深度限制。import sys # 将递归深度上限调到1万层覆盖绝大多数机试场景 sys.setrecursionlimit(10000)但这里我要多嘴一句调高上限是治标不治本。如果递归深度真的会超过几千层更稳妥的方案是把递归改成显式栈的迭代写法。这份资源里有些题的DFS解法特意写了两种版本递归版用于理解思路迭代版用于实际提交。我建议优先掌握迭代版因为考场上的编译环境不一定允许你改递归上限。4.3 输出格式的隐形陷阱多一个空格少一个空格都不行OJ判题对输出格式是逐字符比对的。有时你答案完全正确仅仅因为多行输出之间多了个空格或少了换行就是不给过。这个坑我在资源里的题解中也见到过处理方法。最稳妥的做法是把所有输出部分先构造成一个列表最后用join拼接输出。不要一边算一边print因为print默认会在末尾加上换行很容易在循环里多出多余的换行符。# 推荐统一收集输出最后一次性打印 output_lines [] for item in results: output_lines.append(str(item)) sys.stdout.write(\n.join(output_lines))这样处理之后末尾不会有多余的换行中间行之间也保证只有一个换行。相比之下之前我见过有人用循环print结果每两个结果之间多了一个空行排查了半天才发现是print和print的换行叠加。不过要注意有些OJ要求最后一行也需要换行符这种最保险的做法是join之后再加一个\n但这需要根据具体的OJ平台来测试我在本地跑没有统一标准。资源里有些题目的注释里直接写了「这个OJ要求最后加换行」说明收录时已经踩过一遍了这种经验直接拿来用即可。4.4 递归和循环里修改同一份列表别名问题让人防不胜防Python的列表默认是引用传递你在函数里把列表作为参数传进去函数内部修改会直接改动原始列表。这在机试里经常出问题尤其是DFS回溯时你会把当前路径加入结果列表结果最后发现结果列表里全是同一个路径的重复。现象就是输出全是空列表或者全是同一个内容。# 错误示范直接把path加入result result.append(path) # 之后改pathresult里的内容也跟着变 # 正确方式拷贝一份再存 result.append(path[:]) # path[:]产生新列表断开了引用关系这行path[:]就是玄学所在很多Python机试新人都栽在这里。如果你存的是字符串或者数字不会遇到这个问题但题目里要你输出的是路径、排列、组合时一定要记得拷贝。我在拆这份资源时特意数了一下至少有十几道题目的题解里用了path[:]或者copy.copy()来防止这种引用污染说明这个坑在机试里太常见了。如果你在调试时发现结果列表的长度是对的但内容全一样十有八九就是这个原因。4.5 全局变量与局部变量函数内修改count不生效另一个高频坑是Python的作用域问题。你在函数外定义了一个计数器count想着在DFS函数里每次找到一个答案就count加一结果函数执行完回到主程序count还是0。原因是Python规定在函数内部对变量赋值时默认这个变量是局部变量除非你用global声明或者把它放在列表中。现象非常迷惑很多人在递归里排查了半天最后才发现是作用域问题。count 0 def dfs(...): global count # 没有这行count的修改不会生效 count 1我在资源里的DFS题解中看到有些代码为了不写global干脆把计数器放在列表里比如count [0]然后函数内部用count[0] 1这样也能绕过作用域限制。两种方式都行但global更直白一些。如果你写的是类方法那就用self.count更合适。反正核心就是记住一点Python的赋值不等于修改函数内默认处理的是自己作用域里的东西。这类问题最好在平时刷题时就形成肌肉记忆不然真到了考场心态一紧张调试半天还摸不着头脑。5. 进阶验证一份Python机试刷题资源好不好的硬核方法5.1 用「复现而非照抄」的方式检验代码质量我把这个资源里的代码用了一段时间后摸索出一套检验刷题资源质量的方法分享给你参考。第一步不看答案先自己写一遍解法写完之后打开资源里的题解对比。第二步检查你们的思路是否一致如果不一致不要急着说谁对谁错先拿到本地跑几个自测用例。第三步再把题解代码里所有注释遮掉试着自己重新给代码补注释如果补出来的注释和原文差距不大说明你是真的理解了这段代码。这个方法看起来费时但一次能顶十次盲目抄题。5.2 给代码做「极端值压力测试」别只跑示例用例几乎每个刷题资源附带的题目都有示例输入输出但示例通过绝不代表代码在OJ上能通过。我自己的习惯是拿到任何一段题解代码都先构造几个极端用例去跑比如空数组、单个元素、全是相同元素、数组长度达到题目上限。这个过程用不了几分钟但能筛掉八成以上隐藏的边界问题。# 极端用例自测模板跑完示例之后必做 import random def stress_test(solve_func, input_builder, max_size1000): # 循环生成100组随机数据对比函数输出是否崩溃 for seed in range(100): test_input input_builder(max_sizemax_size) try: solve_func(test_input) except Exception as exc: print(seed , seed, 输入 , test_input) print(异常信息:, exc) return False return True这个测试模板的思路是即使你不知道正确答案是什么只要函数在各种随机输入下都能稳定运行不抛异常最基本的健壮性就有了保障。如果某段代码在压力测试中频繁崩溃那不管它的算法多巧妙在机试里兑现不了就是零分。我在拆这份资源时拿这个模板跑了它的大部分代码有极少数题目在超大输入下运行时间偏长但胜在内存占用稳定没有异常退出。所以整体质量我还是比较认可的。5.3 把题解代码改写成自己的「节省内存版」机试对内存的限制通常在几百兆以内Python本身的运行内存就比C高不少所以写代码时还是要有点节俭意识。这份资源里有一部分题解在内存使用上做了优化比如用一个变量代替一整个数组来做递推把二维状态压缩成一维。这个思路很值得自己练习。当你把资源里的普通版本代码改写成空间优化的版本时你就真的理解了这道题的状态转移本质而不是只会背模板。# 滚动数组示例斐波那契类递推问题省空间 prev, curr 0, 1 for _ in range(n): prev, curr curr, prev curr这个写法看起来平平无奇但它背后是「每一步只需要前两个状态」这个观察。在资源里有一道阶梯跳跃题它就用到了这种滚动更新的思路。我后来把这种优化方式迁移到其他动态规划题目里效果出奇地好内存占用直接砍掉一个数量级。在机试里内存越稳心里越踏实也越不容易因为内存超限导致整场考试崩盘。5.4 把这份资源变成你自己的错题本资源是固定的但你的错题本是你自己的。我建议把这份资源的题目按难度分成三档一眼就能写出来的、看题解能写出来的、看题解也要想半天的。第三档是你真正要突破的薄弱环节值得反复练三到五遍。第二档是考试中主要拿分的部分至少练到完全不看题解能写出完整代码。第一档就是你的模板库考前最后一天只过这一档。从那以后我每次拿到任何刷题资源都会强制自己走一遍这个流程先按题型标记、再写模板函数、再跑极端用例、最后整理自己的错题本。这么做最大的收获不是把代码背下来而是碰到新题时能快速判断它属于哪个已知题型并调用对应的模板思路。希望这份拆解能帮你在机试准备路上少走几条弯路把宝贵的时间真正花在有效练习上而不是反复踩别人踩过的坑。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑