1. 项目概述与背景分析
1.1 网易有道2017内推编程题是什么
先把这个标题拆开看:网易有道、2017、内推、编程题。四个词放在一起,核心就是当年网易有道校招内推环节给候选人做的那套在线笔试题目。内推和正常网申的区别在于,内推简历会被部门直接捞起来,一般可以跳过部分初筛流程,候选人拿到笔试链接的时间也往往比正式批更早。所以这套题在当时的求职圈里,流传度非常高,很多准备进互联网大厂做开发的人,不管是不是投了有道,都会找出来刷一遍。
这套题具体考什么?我印象里涉及的内容以编程基础为主,包括字符串处理、数组操作、简单数据结构运用、边界条件处理这些。从难度上看,它不是那种需要背板子的竞赛题,而是更贴近“给你一个业务场景,让你用代码快速解决”的风格。对候选人来说,能通过这道题,说明基本编码能力过关、思维够清晰。
1.2 为什么现在还要回头看这套题
你可能会问:2017年的题,现在都过去这么多年了,还有什么参考价值?
说实话,这类互联网公司的内推笔试,题目本身会换,但考察的底层能力一直没变。字符串处理、边界控制、时间空间复杂度意识,这些到现在依然是面试手撕代码的重点。尤其是对有道这样的公司,业务里大量涉及文本内容处理,所以笔试出字符串题是再正常不过的事。反过来看,现在很多刷题平台上的题目虽然更花哨,但不少从思路上都能回溯到当年这类经典题。
另外,这套题还有一个特殊价值:它非常像2025年Python一级编程题的出题风格——围绕基础语法、简单逻辑、字符串操作展开,不考复杂算法,但很考验你的细节处理能力。如果你正在准备Python编程等级考试,或者刚开始刷题,拿这套题练手其实特别合适。
1.3 什么样的人适合重点研究这套题
- 准备参加互联网公司校招、内推的在校生,尤其是目标岗位是后端开发、测试开发、客户端开发的。
- 正在系统学习Python基础语法,想通过真实题目检验自己掌握程度的初学者。
- 备考Python等级考试一级的考生,需要大量基础编程题来巩固手感。
- 负责校招出题或面试的工程师,想参考经典题型的考察点设置。
这篇文章我会以Python 3为例,把这类题目从读题、解题思路、代码实现到踩坑复盘完整过一遍。你不需要有很高的算法基础,只要能看懂基本的for循环、if判断、字符串切片,就能跟着走下来。
2. 解题前的通用准备与思路框架
2.1 环境准备:选对语言和工具
刷题之前,先把环境搞定。我用的是Python 3.8+,直接在本地终端里运行,没有依赖任何特定的IDE。如果你习惯用PyCharm、VS Code或者在线编辑器,都行,关键是保证写出来的代码能够在标准输入输出模式下运行。
为什么强调标准输入输出?因为在线笔试的判题系统,基本都是通过stdin读取输入,检查stdout的输出。很多新手在IDE里跑得好好的,一提交就报错,原因往往就是用了input()但不清楚判题系统给的输入格式,或者print()的格式和题目要求不完全一致。
建议你在本地也模拟这种输入方式。比如题目要求输入一个字符串,你就直接在终端里粘贴;要求输入多行,就按行输入。这样提交的时候心里有底。
2.2 拿到题目先做三件事
发现很多人一看到题目就急着写代码,结果写到一半发现理解偏了,又推倒重来。我自己的习惯是,不管题目多简单,先花一两分钟做三件事:
- 明确输入格式:是一行还是多行?每个字段之间用什么分隔?有没有可能为空?
- 明确输出格式:是逐行输出还是单行输出?结尾有没有空格要求?
- 框定边界情况:字符串会不会是空的?数组长度有没有上下限?如果输入特别长,会不会超时?
这三件事想清楚,代码写起来基本不会跑偏。
2.3 这类题的核心考察点
网易有道这套题,以及Python一级编程题,核心考察点就那么几个:
- 字符串的基本操作:切片、拼接、查找、替换。
- 列表的基本操作:遍历、追加、排序、去重。
- 逻辑判断:if-elif-else的嵌套与边界条件。
- 循环控制:for循环、while循环的正确使用。
- 输入输出格式的精确控制。
- 时间复杂度和空间复杂度的基本意识,尤其是当数据量变大时,你的解法能不能撑住。
把这几点练扎实,比背多少偏题怪题都管用。
3. 典型真题拆解与完整实现
3.1 题目一:字符串循环移位包含问题
先说一道当年流传比较广的题:给定两个字符串A和B,判断A循环移位后是否能包含B。
什么意思呢?举例来说,A = "AABCD",把A循环移位,可以得到"AABCD"、"ABCDA"、"BCDAA"、"CDAAB"、"DAABC"等等。如果B = "CDAA",那么显然在某次移位后的结果里是可以找到"CDAA"的,所以应该输出True。
很多人第一次看到这题,第一反应是把所有循环移位的结果都生成出来,然后逐个判断。这个思路对,但不够好。
实际上有一个非常经典的技巧:如果A循环移位后的结果包含B,等价于在 A + A 这个字符串中能直接找到B。
为什么?因为 A + A 已经包含了A所有循环移位可能的起点位置。比如 A = "AABCD",A + A = "AABCDAABCD",那么任意一次循环移位的结果,其实都是这个新字符串中某个长度为len(A)的连续子串。你要判断的是某个循环移位后的字符串是否包含B,而B的长度可能小于A,所以直接在A + A中查找B就够了。
代码写出来非常简单:
def can_shift_contain(a: str, b: str) -> bool: if not a or not b: return False combined = a + a return b in combined if __name__ == "__main__": a = input().strip() b = input().strip() print(can_shift_contain(a, b))这里我做了空字符串的防御性判断。虽然很多题目不会专门给空字符串用例,但写上没坏处。还有一点要注意:input()读进来的字符串可能自带换行符或首尾空格,所以统一用strip()处理一下。
这个实现的时间复杂度是O(n+m),其中n是A拼接后的长度,m是B的长度。Python的 in 操作在字符串查找时底层做的是高效匹配,对于笔试场景完全够用。
3.2 题目二:数组元素去重排序问题
再来看一道数组题。输入一个数组,里面可能有重复元素,要求去重后按升序输出。
这类题在Python里最简单的方式是利用set和sorted的组合:
def dedup_and_sort(arr): return sorted(set(arr)) if __name__ == "__main__": nums = list(map(int, input().split())) result = dedup_and_sort(nums) print(" ".join(map(str, result)))这段代码先把列表转成集合,利用集合的互异性去重,再用sorted排序。整个过程简洁,可读性高,时间复杂度是O(n log n),因为排序的耗时占主导。
但笔试中这道题往往会有更“恶心”的输入格式。比如第一行告诉你数组长度,第二行才是真正的数组元素;或者元素之间用逗号分隔。这时候有人就懵了。其实思路一样,只是解析的时候多写一步:
n = int(input().strip()) nums = list(map(int, input().strip().split())) result = sorted(set(nums)) print(" ".join(map(str, result)))还有一个容易被忽略的点:如果题目要求保持原有相对顺序去重,就不能用set了,因为set会打乱顺序。那种情况常见于要求按第一次出现顺序输出。这时候可以手动维护一个seen集合和一个结果列表:
def stable_dedup(arr): seen = set() result = [] for x in arr: if x not in seen: seen.add(x) result.append(x) return result这种写法虽然代码略多,但体现了你对需求的理解深度,面试时写出来反而加印象分。
3.3 题目三:计算字符出现次数问题
还有一种出镜率极高的题:给定一个字符串,统计每个字符出现的次数,并按某个规则输出。
比如输入"hello world",要统计h、e、l、o、空格、w、r、d分别出现几次。这类题的经典做法是用字典:
def count_chars(s: str): counter = {} for ch in s: counter[ch] = counter.get(ch, 0) + 1 return counter if __name__ == "__main__": s = input() counter = count_chars(s) for ch, cnt in counter.items(): print(f"{ch}: {cnt}")用dict.get(ch, 0)来写,比先判断ch在不在字典里更简洁。每次读取当前计数,如果不存在就默认0,然后加1。
如果题目要求按出现次数从高到低排序输出,就加一步sorted:
for ch, cnt in sorted(counter.items(), key=lambda x: x[1], reverse=True): print(f"{ch}: {cnt}")这里key=lambda x: x[1]表示按字典的值排序,reverse=True表示降序。如果出现次数相同,还想按字符顺序排,可以这样写:
sorted(counter.items(), key=lambda x: (-x[1], x[0]))技巧在于,用负数表示降序,同时第二个排序键x[0]保持升序。这个方法在面试中特别实用,因为很多排序题都会遇到“先按频率,再按字典序”的组合条件。
3.4 题目四:最大公约数与最小公倍数
这类数学题在基础编程题里也特别常见。给定两个正整数,求最大公约数(GCD)和最小公倍数(LCM)。
最大公约数最经典的是辗转相除法,也叫欧几里得算法。核心原理:两个整数的最大公约数等于其中较小数和两数相除余数的最大公约数。递归或循环实现都行:
def gcd(a: int, b: int) -> int: while b != 0: a, b = b, a % b return a def lcm(a: int, b: int) -> int: return a * b // gcd(a, b)为什么最小公倍数可以用这个公式?因为 a 和 b 的乘积等于它们的最大公约数乘以最小公倍数。注意这里要用整除//,因为乘积可能超过普通整数范围,但Python3的整数没有溢出问题,所以直接算也没事。不过用整除更严谨。
边界情况:如果a或b是0,gcd就没什么意义,一般题目会保证输入为正整数。但如果你写工具函数,还是建议加个判断:
def gcd_safe(a: int, b: int) -> int: if a == 0 or b == 0: return 0 ...这个细节在正式面试手写时不一定用得上,但体现了你对异常输入的处理意识。
3.5 题目五:回文串判断
回文串就是正着读和反着读一样的字符串,比如"aba"、"level"、"上海自来水来自海上"。判断一个字符串是否为回文串,最简单的做法是:
def is_palindrome(s: str) -> bool: return s == s[::-1]s[::-1]是Python里反转字符串的写法,非常方便。但这类题有时候会变体:忽略大小写、忽略非字母数字字符。比如输入"A man, a plan, a canal: Panama",要求判断字母数字部分是否构成回文。
这时候就不能直接反转了,需要先过滤:
def is_palindrome_filtered(s: str) -> bool: filtered = [] for ch in s: if ch.isalnum(): filtered.append(ch.lower()) return filtered == filtered[::-1]使用isalnum()判断字符是否为字母或数字,再统一转成小写。这个解法不涉及额外的高级数据结构,思路清晰,是笔试中的标准答案。
如果要求不额外使用额外空间,也就是空间复杂度O(1),那就要用双指针从两端向中间扫描:
def is_palindrome_two_pointer(s: str) -> bool: left, right = 0, len(s) - 1 while left < right: while left < right and not s[left].isalnum(): left += 1 while left < right and not s[right].isalnum(): right -= 1 if s[left].lower() != s[right].lower(): return False left += 1 right -= 1 return True双指针写法在思路上稍微绕一点,但在一些面试场景里,面试官会明确要求“不能使用额外空间”,这时候你就需要拿出这种方案。
4. 高频变体题型与破题方法
4.1 二进制中1的个数
这道题在当年很多公司的笔试里都出现过。给定一个整数,求它的二进制表示中有多少个1。
最容易想到的思路是:不断对2取模判断最后一位是不是1,然后右移一位。但这里有个坑:对于负数,右移在Python里是算术右移,会一直补1,导致死循环。所以更稳妥的做法是用位运算技巧:
def count_one(n: int) -> int: count = 0 while n: n = n & (n - 1) count += 1 return count这个技巧的原理是:n & (n - 1) 会把n的二进制表示中最右边的那个1变成0。所以循环一次消掉一个1,循环次数等于1的个数,效率很高,而且天然处理了负数在Python中的无限位表示问题。更准确说,Python的负数补码表示是无限长的,但按位与操作后的结果会收敛,所以能正常算出来。
如果你想要常规写法,也可以结合掩码一位一位判断:
def count_one_mask(n: int) -> int: count = 0 for i in range(32): if n & (1 << i): count += 1 return count这种写法更直观,但效率不如n & (n-1)方案。笔试时首选位运算技巧,因为代码短且高效。
4.2 括号匹配问题
括号匹配几乎是面试必考。给定一个只包含(、)、{、}、[、]的字符串,判断括号是否有效,也就是说左括号必须用相同类型的右括号闭合,且顺序正确。
这类题的标准解法是栈:
def is_valid_brackets(s: str) -> bool: stack = [] mapping = {")": "(", "}": "{", "]": "["} for ch in s: if ch in mapping: if not stack or stack[-1] != mapping[ch]: return False stack.pop() else: stack.append(ch) return not stack这里用字典mapping来映射右括号对应的左括号,遇到左括号就入栈,遇到右括号就检查栈顶是否匹配。最后栈为空说明所有括号都正确闭合。
这个题目看着简单,但实际写出bug的概率不低。常见问题包括:忘记判断栈为空就pop、遍历结束后忘了检查栈是否为空、只处理了小括号没处理中括号和大括号。写完后建议自己拿几个边界用例测一下,比如"("、")("、"([)]"、"([])"。
4.3 连续子数组最大和问题
这题从难度上比前面几个高一个档次,但在内推题里也偶有出现。给定一个整数数组,找到一个具有最大和的连续子数组,返回其最大和。
经典解法是Kadane算法,核心思想是:遍历数组,维护当前子数组的和current_sum,以及全局最大和max_sum。如果current_sum加上当前元素后还没有当前元素本身大,那就从当前元素重新开始。
def max_subarray_sum(nums): if not nums: return 0 max_sum = nums[0] current_sum = nums[0] for num in nums[1:]: current_sum = max(num, current_sum + num) max_sum = max(max_sum, current_sum) return max_sum这个思路用一句话解释就是:要么把当前元素加到之前的子数组后面,要么抛弃之前的累加和,从当前元素重新开始。之所以取max,是因为如果之前的累加和是负数,那加上它只会拖累当前元素。
例如输入[-2,1,-3,4,-1,2,1,-5,4],遍历过程会得到最大子数组为[4,-1,2,1],和为6。你可以在草稿纸上手动推演一遍,感受一下current_sum是怎么一步步变化的。
5. 实战中的输入输出陷阱与应对策略
5.1 多行输入测例的处理
在线笔试最烦人的不是算法,而是输入解析。很多时候你的算法完全没问题,但程序在运行测试用例时直接报错或结果不对,就是因为卡在输入上。
最常见的一种情况是:题目说“输入包含多组测试用例,每组占两行”。这时候你不能只读一次就完事,而是要用循环读到文件末尾,也就是EOF。
import sys for line in sys.stdin: line = line.strip() if not line: continue # 假设每两组数据为一轮,第一行是数组长度,第二行是数组元素 n = int(line) nums_line = sys.stdin.readline().strip() nums = list(map(int, nums_line.split())) # 处理...这里用sys.stdin而不是input(),是因为在循环处理多行时,sys.stdin的迭代方式更稳定,也不会因为readline读到空字符串而中断。
注意if not line: continue,这个判断可以过滤掉空行。有些测例会在数据之间插入空行,不处理的话int("")会直接抛异常。
5.2 字符串输入中隐藏空格的处理
有些题目里的字符串是带空格的,比如句子反转、单词统计。如果用input().split(),它默认按空白字符分割,会把多个连续空格压缩成一个,同时还会过滤掉换行符。这在大多数情况下是好事,但如果你要保留原始空格,就要用别的办法。
举个例子,输入"hello world",中间有两个空格,要求统计所有字符。这时用input().strip()可以保留字符串内部的所有空格,但首尾空格会被去掉。如果题目明确说首尾也可能有空格,那就连strip()都不要用,直接用input(),然后去掉末尾的换行符。
这里有个小技巧:
s = input().rstrip('\n')rstrip('\n')只去掉行尾的换行符,不影响其他字符。这个细节在处理严格匹配输出的题目时非常重要。
5.3 输出格式的精确控制
输出格式是很多人的失分重灾区。比如要求“每个数字之后跟一个空格”还是“每个数字之间用一个空格,行末不能有空格”。这两种要求看似相同,实际输出字符串却差一个尾随空格。判题系统通常把空格也算进结果比较,所以多余空格会导致Wrong Answer。
推荐的做法是先把结果收集到列表里,最后用join生成最终字符串:
result_list = [str(x) for x in result] print(" ".join(result_list))这样就不会有行尾空格问题。如果你用的是Python 3,print()默认会在结尾加换行,大多数题目都接受。如果遇到某些平台要求不能有多余换行,可以用print(..., end="")。
5.4 时间复杂度的隐形门槛
有些基础题,看起来直接暴力循环就能过,但一提交就超时。比如数组里找重复元素,如果两层循环嵌套,数据量一大就崩。这种题的正确做法是利用set或者dict把时间复杂度降到O(n)。
原因是:在线判题系统对Python程序的运行时长限制通常比较宽,但也有限度。当数组长度到10^5级别时,O(n^2)的算法基本不可能通过,而O(n)或O(n log n)的算法可以在1秒内跑完。
有个简单的估算公式:你的算法执行的基本操作次数不要超过10^7。如果n是10^5,那么O(n)是10^5,没问题;O(n log n)大约是1.7×10^6,没问题;O(n^2)是10^10,必挂。任何时候,做题前先看一眼数据范围,再决定用什么算法。
6. 常见问题与排查技巧实录
6.1 本地运行正确,提交却报错
这是我被问得最多的问题。先说结论:本地正确,提交报错,90%是输入输出格式的问题。
- 你可能用的是input(),但测例包含多组数据,需要循环读取。
- 你可能输出了调试信息,比如print(a)之类的,判题系统把调试输出和答案混在一起。
- 你可能在输出数字时带了类型括号,比如print(str([1,2,3])),这会把列表的方括号也打出来。
建议你在提交前做一次“干净版”检查:把代码里所有print都清点一遍,只保留真正要输出的内容。
6.2 Python的缩进问题
缩进在Python里是语法的一部分,错一点就报IndentationError。笔试环境下没有IDE的自动缩进提示,很容易出现tab和空格混用的情况。
统一用4个空格缩进。不要用tab。虽然现代编辑器可以自动处理,但在线网页编辑器里偶尔会出问题。如果提交后看到IndentationError,优先检查是不是混用了缩进符。
6.3 递归深度限制
有些题目你可能会用递归实现,比如二叉树遍历、深度优先搜索。Python的默认递归深度大约是1000层,一旦超过就会抛出RecursionError。
解决办法有两个:一是改成循环加栈的方式;二是在代码开头增加递归深度限制:
import sys sys.setrecursionlimit(1000000)但递归深度限制调大后,可能会增加内存占用,甚至导致程序崩溃。所以更好的做法是想清楚递归层数到底有多深,如果可能超过1000层,就要考虑非递归写法。
6.4 数据类型的坑
Python的int没有长度限制,这是个优势,但如果你习惯性地用C++的思路去处理,可能会写出不必要的取模运算。另外注意,除法/返回的是浮点数,而整除//返回的是整数。在需要精确整数运算的场景,比如求最大公约数、最小公倍数,一定要用//,否则可能引入浮点误差。
还有一点:map(int, input().split())返回的是map对象,在Python3里不是列表。如果你要多次使用这个结果,最好先转成list。
nums = list(map(int, input().split()))不转列表的话,第一次遍历之后map对象就空了,第二次遍历什么也拿不到。这是一个非常隐蔽的小坑,很多人在循环里用了一次map没问题,第二次再遍历时结果为空,找了半天才发现是这里的问题。
6.5 常见问题速查表
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
| 提交报答案错误,但本地测试通过 | 输出格式与题目要求不一致 | 检查是否有额外空格、换行、调试输出 |
| 提交报运行时错误 | 输入格式解析错误或递归过深 | 用sys.stdin逐行读取,检查递归次数 |
| 大数组用例超时 | 算法复杂度太高 | 用set/dict降低复杂度,减少嵌套循环 |
| 读取到的数据多出换行符 | strip()使用不当 | 用rstrip('\n')只去除行尾换行 |
| 第二次遍历map对象没数据 | map对象只能迭代一次 | 先转成list再使用 |
| 数组排序后结果顺序和预期不符 | set去重后顺序被打乱 | 如需稳定去重,手动维护seen集合 |
6.6 我踩过的几个具体坑
有一年我在一个在线笔试平台做模拟题,遇到一个字符串反转的题目,要求反转每个单词但保持单词顺序不变。输入是"I am a student.",期望输出"student. a am I"。
我一开始写的是:
words = input().split() print(" ".join(words[::-1]))本地跑没问题,一提交就报错。我把题读了三遍才发现,输入里可能包含多个连续空格,而split()会把它们都吞掉,完美还原原始空格的要求没被满足。比如原始输入是"I am a student.",中间有两个空格,期望输出也要保留两个空格。
所以后来我改成用正则分割:
import re parts = re.split(r'(\s+)', input())这样一来,不仅单词被分割出来,空格也被保留在separator中。再反转整个列表再拼接,就能精确还原原始格式。
这个题让我意识到:很多基础题看似简单,实际上考察的是你对输入数据的尊重程度。不要想当然地认为空格无关紧要,在线判题系统可不会给你通融。
7. 从真题看能力提升方向
7.1 刷题不在多,在于复盘
一套网易有道2017内推题做完,不要急着去刷下一套。我建议你花同样的时间复盘一遍,问自己几个问题:
- 每道题我都用了几种解法?
- 最优解法的原理我能不能用大白话讲清楚?
- 我在哪些地方卡壳了?卡壳的原因是知识点缺失还是思路不清晰?
- 如果题目数据规模再扩大10倍,我的代码还能扛住吗?
把这些问题写下来,比多刷十道重复题型更有用。
7.2 Python基础知识点对照
这套题对应的Python基础知识点,我整理了一张对照表:
| 题目类型 | 涉及基础知识点 | 记忆关键词 |
|---|---|---|
| 循环移位包含 | 字符串拼接、in查找 | A + A 包含所有循环移位结果 |
| 数组去重排序 | set、sorted、map | 去重用set,保序用手动遍历 |
| 字符计数 | 字典、get方法 | dict.get(key, default) |
| 最大公约数 | 辗转相除法 | while b: a, b = b, a % b |
| 回文判断 | 字符串反转、双指针 | s[::-1] 或两端向中间扫描 |
| 二进制1个数 | 位运算 | n & (n-1) 消除最后一个1 |
| 括号匹配 | 栈 | 左括号入栈,右括号弹栈匹配 |
| 最大子数组和 | 动态规划思想 | current_sum = max(num, current_sum + num) |
这些知识点如果你都能熟练运用,那说明Python基础语法这块已经很扎实了。
7.3 面试时的手撕代码技巧
笔试之外,这套题也可以当作面试手撕代码的练习素材。面试时写代码和笔试有一个很大区别:面试官会看你的思考过程,你一边写一边要说出为什么这么写。
比如写循环移位包含那道题时,你可以这样说:我先把A复制一遍拼接到后面,因为循环移位后的所有结果,本质上都是A+A这个字符串里的连续子串,然后我直接在A+A里查找B,这样就把循环移位问题转化成了普通的子串查找问题。这样的表述,比直接闷头写代码要加分得多。
另外,面试时写完代码,一定要主动说边界情况。比如“如果输入为空字符串,我这里返回False”“如果数组只有一个元素,我的代码应该能正常处理”。面试官很看重这一点,因为线上系统的隐藏用例往往就是这些边界值。
8. 后续进阶方向与个人建议
8.1 从基础题到中等难度题的过渡
把这套题吃透之后,下一步就是向更复杂的题型进阶。推荐按这个顺序来:
- 先把字符串类题目刷熟,重点练习KMP算法、最长公共前缀、字符串压缩等。
- 再练数组和链表,掌握双指针、滑动窗口、前缀和这些高频技巧。
- 之后是哈希表、二叉树、递归回溯,这些是面试的绝对核心。
- 最后才是动态规划和图论,需要更多时间沉淀。
每次进阶都不要太着急,一个知识点吃透了再进入下一个。就像练武功一样,扎马步都站不稳,就去练轻功,只会摔得更惨。
8.2 保持手感的方法
我个人的经验是,每周至少做2到3道题,保持手不生。不需要每次都做大题难题,基础题反而更容易暴露出手感的下降。就像运动员每天都要做基础训练一样,代码基本功也需要持续练习。
做题的时候,给自己限定时间。简单题控制在10分钟以内,中等题控制在30分钟左右。如果超过时间还没有头绪,不要硬耗,直接去看题解,理解思路后再自己重写一遍。
8.3 写在最后的一些实话实说
这些年我见过很多刷题很猛的人,题库刷了上千道,但真到面试现场,连一道简单的字符串反转都写不利索。也见过一些刷题量不大,但每道题都研究得很透的人,反而能拿到不错的offer。所以刷题的数量不是关键,关键是你有没有把每道题背后的思维模型真正内化。
这套网易有道2017内推题带给我的收获,不是某个具体的解题技巧,而是一种“把复杂问题简化成基础操作”的能力。任何复杂的业务需求,拆到最后都是一次次字符串处理、数组遍历、条件判断的组合。把这些基础动作练成肌肉记忆,你面对新题的时候才能游刃有余。
我个人在实际操作中还有一个体会:把这些经典题的答案写下来,隔一两周再重新写一遍,你会发现第一次写的时候忽略了很多细节。第二次写的时候,你对边界条件的处理会自然变得更严谨。这个过程就是进步。