ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

编程中等题突破指南:五大核心题型与实战调试技巧

编程中等题突破指南:五大核心题型与实战调试技巧 经典编程练习——“中等卷”这五个字我在不同场合见过太多了。培训机构管它叫“拔高题”刷题网站管它叫“进阶题库”还有不少跟着网课学的朋友管它叫“魔鬼关卡”。但说句实在话所谓中等卷练的根本不是偏题怪题它卡住的从来不是“没见过”而是“想到过但写不顺”。本篇就专门拆一下这类练习题背后真正在考核的东西从能力模型、题型拆解、代码实现到调试思路一条线捋清楚。不管你是刚学完语法准备进阶的初学者还是刷题经常卡在中等题的老手这篇都值得停下来看看。1. 中等卷到底在练什么先把能力模型拆明白1.1 中等卷和基础卷的本质差异不止是加难度基础卷的题目很多时候是“给你一个明确规则你照着实现”。比如把一个数组排序、把字符串反转、算个斐波那契数列。这类题锻炼的核心是“语法熟练度”——你会不会写循环会不会调用库函数能不能把伪代码翻译成真实代码。但中等卷完全换了一套考核逻辑。它不再满足于“你知不知道某个知识点”而是考察“你在多个知识点交叉时能不能把它们组织成一个完整的解决方案”。一个典型的中等题往往是这样的它需要你先把实际问题抽象成数据结构再选择合适算法最后还要处理边界条件。这三步缺一不可而且顺序不能乱。举个最典型的例子——“给定一个整数数组找出其中三个数使得它们的和最接近目标值”。基础卷的思维是三层循环暴力枚举全部算一遍取最小值。这没错但时间复杂度O(n^3)数据量一大就超时。中等卷的思维则是先排序再用双指针把三层循环压成两层时间复杂度降到O(n^2)。你看这就不是单纯的语法问题了而是“你会不会根据数据规模反推算法”“你知不知道排序能简化搜索问题”这种更高一层的能力。1.2 五大核心能力为什么很多题你“看得懂但写不出”我在带人的过程中发现一个规律卡在中等卷的人很少是语法不会而是下面五件事至少有一件没做到位。第一抽象建模能力。题目描述往往是一段生活化的文字你得把它翻译成“数组”“链表”“树”“图”“集合”“映射”这些计算机能理解的结构。这个翻译过程越熟练做题速度越快。第二复杂度预判能力。拿到题先看数据范围如果n≤10^5O(n^2)基本就危险了如果n≤20哪怕指数级算法也有机会。这种判断不是玄学是可以通过练习养成的习惯。可太多初学者根本没有这个意识一上来就照最直观的写法写等超时了才回头优化浪费了大量时间。第三边界条件敏感度。我检查过很多人的代码发现一个特别有意思的现象主逻辑写到80分的水平但边界条件一个都没考虑。空数组怎么办只有一个元素怎么办两个元素相等怎么办目标值极小极大怎么办这些细节看着不起眼但恰恰是判题系统最喜欢埋雷的地方。第四调试定位能力。程序跑挂了输出不对了怎么定位是逻辑问题、边界问题还是数据类型溢出问题中等卷的题目往往逻辑链更长一旦出错靠“瞪眼法”看不出问题必须得有系统地调试思路。第五代码组织能力。一段代码是写成200行的面条式(Spaghetti Code)还是拆成三五个逻辑清晰的小函数完全体现了程序员的基本功。这种能力在中等卷阶段就应当养成否则到了项目阶段会更痛苦。1.3 一张表看懂基础卷与中等卷的差异为了说得更直观我做了一张对比表对照着看会非常清晰维度基础卷中等卷核心目标把语法用对把问题拆明白典型数据量无限定或很小有明确范围需据此选算法数据结构数组、字符串为主数组、链表、二叉树、栈、队列、哈希表混合出现算法复杂度不做硬性要求通常要求O(n)到O(n log n)边界条件一般比较友好必须显式处理否则必挂常见陷阱少偏语法细节多偏逻辑和极端输入考核本质你是否学会了你是否能灵活运用这张表不是我拍脑袋编的而是我翻了几百道题目之后总结出来的规律。建议你把它存下来每次做题之前对着它问自己现在这道题考的到底是哪种能力省得你刷了几十道题还在原地打转。2. 核心题型与思路拆解中等卷最爱考的五大族2.1 数组与双指针排序之后世界变得简单数组是编程练习里出现频率最高的数据结构而双指针是解决数组问题最经典的套路之一。它的核心思想并不复杂用两个指针或下标同时遍历数组通过控制指针的移动策略把原本需要两层甚至三层循环的问题优化成一层循环。典型的应用场景有这么几类有序数组的两数之和给定一个升序数组和一个目标值找两个数使它们的和等于目标值。暴力枚举O(n^2)双指针左右夹逼O(n)。三数之和三个数的和为零找出所有不重复的三元组。排序后固定一个数剩下两个数用双指针扫时间复杂度降到O(n^2)。移除元素/去重原地移除数组中所有等于某个值的元素返回新长度。快慢指针一个读一个写一次遍历搞定。盛最多水的容器两根柱子之间能装多少水。左右指针每次移动较矮的那一侧保留可能更大的面积。双指针的精髓在于你要想清楚“指针移动的依据是什么”。比如两数之和因为数组是升序的和太大说明右指针应该左移和太小说明左指针应该右移而盛水问题指针移动的依据是“哪边矮就移动哪边因为矮的已经不可能贡献更大面积了”。我在教学时经常遇到一个误区有人觉得双指针不就是两个循环变量嘛我会写。但真到了具体题里指针的初始化位置、移动条件、终止条件这三件事只要有一件想得不透彻写的代码就会在边界上翻车。所以建议你练双指针的时候先别急着写代码拿出纸笔模拟一遍指针的移动过程把每一步的状态都写下来你会对它有完全不同的理解。2.2 链表操作细节决定成败链表题是中等卷里非常容易失分的部分原因很朴素——它太依赖指针操作了。一旦涉及到链表的反转、删除、合并就会牵涉到“前驱节点”“后继节点”这些概念。比数组复杂的地方在于数组你可以通过下标随机访问而链表只能顺着next走因此你必须在脑子里维护好“当前节点是谁”“它的前驱是谁”“它的后继是谁”这三条信息。举一个特别经典的例子——“反转链表 II”反转从位置m到n之间的链表节点。很多人一看就会一写就错。错在哪儿错在反转中间段之后你得把这一段和前驱、后继正确连接起来。这一步只要有个特殊情况没考虑到比如m等于1没有前驱代码就崩了。另一个高频考点是“链表的中间节点”。你可以先遍历一遍数出长度再走一半也可以用快慢指针快指针每次走两步慢指针每次走一步快指针走到末尾时慢指针正好在中间。后者只需要一次遍历明显优雅得多而且在很多场景下可以直接复用。链表题的实际操作建议就三条如果链表可能被改头比如删除第一个节点、反转整个链表一定要用虚拟头节点(dummy node)技巧。它本来就是null没有实际意义但可以让代码不用单独处理“头节点被修改”的情况。涉及指针移动的地方务必先备份后更新。经典顺序是“先保存next再改指针方向”否则一改就找不着后面的节点了。画图。链表题不画图等于闭着眼睛开车哪怕画得歪歪扭扭只要能标清楚每一步的指针指向就能极大降低出错概率。2.3 字符串处理与哈希表空间换时间的大杀器字符串在中等卷里通常不单独出题而是喜欢藏在别的知识点里。比如判断两个字符串是否是异位词、最长无重复子串、字母异位词分组。这类题有一个共同的解题根基——哈希表。哈希表的价值在于它能把“查找”的时间复杂度从O(n)降到O(1)。举个例子最长无重复子串这道题暴力解法是把每个字母都作为起点向后扩展直到出现重复复杂度O(n^2)。而滑动窗口哈希表的方案只需要O(n)用左指针标记当前子串起点右指针不断右扩遇到重复字符就把左指针挪到重复位置的下一位并用哈希表记录每个字符最近出现的位置。还比如“有效的字母异位词”最简单的实现就是统计每个字符出现的次数。你甚至可以不用哈希表直接开一个长度为26的数组把字符映射到0~25的索引上来一个就加一走一个就减一最终全为0就是异位词。这个思路用到的其实就是“广义上的哈希思想”。初学者经常犯的错误是想当然地认为哈希表就是字典字典就是哈希表。严格说哈希表是一种底层数据结构字典是它的典型实现之一。只要理解了“哈希函数把大范围数据映射到小范围空间”这个核心逻辑你就能明白为什么开个长度26的数组能解决很多字母统计问题。2.4 二叉树遍历与递归把大问题拆成小问题二叉树是承接“递归思想”最好的载体。前序遍历、中序遍历、后序遍历、层序遍历每个看起来都简单但真正能把这个知识点用熟的人写出来的代码往往特别干净。以“求二叉树最大深度”为例。递归版本的代码短到让人怀疑是不是漏了什么def max_depth(root): if not root: return 0 return max(max_depth(root.left), max_depth(root.right)) 1就这么几行思路却很值得琢磨一棵树的最大深度等于它的左子树深度和右子树深度中较大的那个再加一。你看这就是“把大问题拆成小问题”的典型示范。递归的终止条件是遇到空节点返回0递归的递推公式是max(left, right) 1。这其实就是把数学归纳法翻译成了代码。与递归配套的还有一个常见考点——“验证二叉搜索树”。很多人直觉是只要每个节点的左孩子比它小、右孩子比它大就是二叉搜索树。但这是错的。二叉搜索树的定义是左子树所有节点都小于根节点右子树所有节点都大于根节点。所以正确做法是给递归函数传一个“取值范围”(min, max)在递归过程中不断收窄这个区间一旦发现节点值不在区间内就返回False。二叉树这块还有一个特别容易忽略的点递归会造成函数调用栈的深度问题。极端情况下如果树退化成一条链递归深度就是节点数可能会导致栈溢出。所以在做这类题的时候你可以顺便思考一个问题如果数据量扩大10倍这个递归写法还能扛得住吗想明白这个问题你对递归的理解就又深了一层。2.5 动态规划入门别慌先找状态转移方程动态规划是中等卷里劝退效果最强的一类题没有之一。但如果你真的把它的本质解剖开会发现它并没有传说中那么玄。动态规划解决的是“子问题重叠”的问题。什么概念拿“爬楼梯”来说你每次可以爬1阶或2阶爬到第n阶有多少种方法你很容易想明白爬到第n阶的方法数等于爬到第n-1阶的方法数加上爬到第n-2阶的方法数。因为最后一步要么是从n-1阶跨1阶上来的要么是从n-2阶跨2阶上来的。这就是状态转移方程而且它大概率也是你接触的第一个动态规划公式dp[n] dp[n-1] dp[n-2]动态规划的难点从来不在于公式本身而在于你得先定义出“状态是什么”。比如“爬到第n阶的方法数”这个状态得自己想出来。你得找出“状态之间如何转移”。比如上面的递推关系。你得处理好“初始化条件”。比如dp[1]1、dp[2]2。你得想清楚“遍历顺序”。是从小到大还是从大到小取决于依赖关系。再比如经典的“零钱兑换”问题给定不同面额的硬币和一个总金额求凑成总金额所需的最少硬币个数。定义状态dp[i]表示凑成金额i需要的最少硬币数然后对i从1到amount遍历对每个硬币面额coin更新dp[i] min(dp[i], dp[i-coin] 1)。这就是一个标准的动态规划流程。我个人的经验是动态规划初学阶段不要直接看题解先把题目描述里所有变量列出来尝试自己定义dp的含义。哪怕定义错了也比不定义强。因为“把问题数学化”这个动作本身就是动态规划的核心内功。等你能把十道经典题的状态定义和转移方程都默写出来你才算真正过了这一关。3. 实操过程与核心环节实现三道经典中等题全流程走一遍3.1 数组题实战三数之和的完整实现题目给定一个包含n个整数的数组nums判断nums中是否存在三个元素a、b、c使得a b c 0找出所有满足条件且不重复的三元组。先说明思路直接三层循环时间O(n^3)数据量一大必然超时。正确姿势是排序双指针。第一步排序。排序的意义在于它让数组有序化双指针的移动有了依据。排序时间O(n log n)。第二步固定第一个数。遍历数组把当前数nums[i]作为三元组第一个数。这里要注意如果nums[i]大于0那后面的数都比它大三数之和一定大于0直接结束循环。第三步双指针找另外两个数。左指针初始指向i1右指针指向数组末尾。计算sum nums[i] nums[left] nums[right]如果sum 0说明找到了一个三元组记录结果并且要跳过所有和当前left、right位置重复的值。如果sum 0说明总和偏小左指针右移让总和变大。如果sum 0说明总和偏大右指针左移让总和变小。去重是这道题最容易丢分的地方。如果不去重同一个三元组会被记录好多次。去重的策略是比较简单的固定第一个数时如果nums[i]和nums[i-1]相等就直接跳过当前的i因为前面的i-1已经把以它为第一个数的所有情况都处理过了。同理在记录结果后也要跳过相同值的left和right。代码实现Pythondef three_sum(nums): nums.sort() n len(nums) res [] for i in range(n): if nums[i] 0: break if i 0 and nums[i] nums[i-1]: continue left, right i 1, n - 1 while left right: total nums[i] nums[left] nums[right] if total 0: res.append([nums[i], nums[left], nums[right]]) while left right and nums[left] nums[left1]: left 1 while left right and nums[right] nums[right-1]: right - 1 left 1 right - 1 elif total 0: left 1 else: right - 1 return res这道题写完之后建议你手动跑几个用例nums [-1, 0, 1, 2, -1, -4]结果应为[[-1, -1, 2], [-1, 0, 1]]。nums [0, 0, 0, 0]结果为[[0, 0, 0]]只有一个三元组。nums [1, 2, 3, 4]结果为[]。3.2 链表题实战反转链表II的逐步推演题目给你单链表的头节点head和两个整数left和right其中left right。请你反转从位置left到位置right的链表节点返回反转后的链表。这道题堪称中等卷链表题的“试金石”。它比反转整个链表多了一个“区间限制”于是还得处理区间外的连接问题。思路拆解如下创建一个虚拟头节点dummy让dummy.next head。这是链表操作里非常经典的一步它让“头节点也可能被修改”的情况变得统一好处理。找到left位置的前一个节点pre。从dummy出发向后走left-1步pre就停在那里。从pre.next开始反转区间内的节点。具体操作是设cur pre.next然后依次把cur后面的节点依次移到pre的后面。这个过程重复right-left次。为了便于理解我举个例子。假设链表是1-2-3-4-5left2right4那么pre指向1cur指向2。现在要反转2、3、4这一区间第一次操作把3移到pre后面链表变成1-3-2-4-5。第二次操作把4移到pre后面链表变成1-4-3-2-5。循环结束反转完成。这个“头插法”反转区间的技巧非常实用代码实现起来也很简洁def reverse_between(head, left, right): dummy ListNode(0) dummy.next head pre dummy for _ in range(left - 1): pre pre.next cur pre.next for _ in range(right - left): next_node cur.next cur.next next_node.next next_node.next pre.next pre.next next_node return dummy.next这里要注意一个特别容易犯的错在移动节点时每个节点的next指针只能被赋值一次如果你没有提前保存next_node就很容易把链表改坏。所以代码里我才专门用了一个next_node变量来存放cur的下一个节点。这个习惯做链表题时务必要养成。3.3 二叉树题实战二叉树的层序遍历题目给你二叉树的根节点root返回其节点值的层序遍历结果即逐层地从左到右访问所有节点。这个题用广度优先搜索(BFS)实现非常自然。BFS天然就是一层一层往外扩展的。实现思路用一个队列存放“当前层的所有节点”。每次循环先记录当前队列的长度level_size这个长度就是当前层的节点数。连续弹出level_size次队列头部把值加入当前层的结果列表。每弹出一个节点就把它的左右孩子非空加入队列。当前层遍历完后把结果列表加入最终结果。每次循环处理一层的做法是BFS做层序遍历的核心。如果不先记录level_size而是边弹边加就会把不同层的节点混在一起导致结果错误。代码实现Pythonfrom collections import deque def level_order(root): if not root: return [] res [] q deque([root]) while q: level_size len(q) level [] for _ in range(level_size): node q.popleft() level.append(node.val) if node.left: q.append(node.left) if node.right: q.append(node.right) res.append(level) return res这道题做完之后建议你考虑一下如果把“从左到右”改成“从右到左”代码要改几行如果要求“之字形”遍历第一层从左到右第二层从右到左第三层再从左到右又要怎么改把这两个变体想明白你对BFS的理解就彻底通了。4. 工具选型与编程环境配置练题前先把装备整明白4.1 语言选择Python、C、Java记法对比中等卷的练习语言选择不需要太纠结。我的建议是如果你已经工作就选你最熟悉的语言如果你还在学习阶段Python是最省事的它语法简洁写题速度最快能把更多精力集中在“算法思路”上。C适合想死磕性能和底层细节的人而Java则适合从入门就面向工程的人。下面是三道题在三种语言下的一些对应写法差异你可以快速感受一下操作PythonCJava数组排序nums.sort()sort(nums.begin(), nums.end())Arrays.sort(nums)队列操作collections.dequestd::queue / std::dequeLinkedList / ArrayDeque哈希表dictunordered_mapHashMap链表定义class ListNodestruct ListNodeclass ListNode我个人的观点是不要频繁换语言。很多人今天用Python刷明天觉得C更酷又切过去结果两边的API都不够熟悉做题效率大打折扣。选一种坚持至少50道题再考虑换不换。4.2 本地环境与在线模板一个趁手的调试框架在线刷题平台自带编辑器但往往不适合复杂调试。我的习惯是在本地建一个统一的项目目录每个题目建一个文件文件里同时包含题目描述链接、解题思路、复杂度分析、标准测试用例和主函数调用。这样刷过的每一道题将来都还能翻出来快速回忆。下面是我常用的一个Python文件模板仅供参考 题目编号XXX 题目链接XXX 难度中等 思路 1. 2. 复杂度 - 时间O(?) - 空间O(?) def solve(nums): # 主逻辑 pass if __name__ __main__: # 测试用例 test_cases [ ([1, 2, 3], 期望结果A), ([0, 0, 0], 期望结果B), ([], 期望结果C), ] for args, expected in test_cases: result solve(args) print(f输入: {args}, 输出: {result}, 期望: {expected})这个模板的作用不是让你少写几行代码而是让你养成“每个题都自测多组数据”的好习惯。很多人在线提交失败根本原因是本地就只跑了一个官方示例边界情况一个没测交上去当然要靠判题系统教做人。4.3 代码格式化与命名规范从练习期就守住底线中等卷的题目逻辑通常不会短到三五行代码可读性就开始变得重要。我见过不少朋友把变量命名为a、b、c函数写成一百行的面条当时自己能看懂过两周回来看一脸懵。我在这里给几个实在建议变量名要表意。left、right、slow、fast、pre、cur、next_node每个都一目了然。函数要短。一个函数尽量只做一件事如果函数体超过20行思考是不是该拆分了。关键逻辑加注释。不需要每行都注释但算法核心的那几行写一句注释说明“这里为什么这么做”以后复习会非常高效。统一缩进风格。Python用4空格C用4空格或Tab都行但同一文件里必须统一。判空优先。函数入口先处理空输入避免后续逻辑对None或空容器做操作时报错。这些都是老生常谈但确实是很多人到工作之后才被迫养成的习惯。如果能在刷题阶段就刻意练习性价比极高。5. 常见问题与排查技巧实录那些年我们一起踩过的坑5.1 边界条件翻车现场中等卷最常见的翻车场景不是算法写不出来而是边界没处理干净。我总结出四个高频边界雷区每一个都是我真实踩过或者帮人排查过的。第一空输入。数组是空的链表是空的树是空的。在函数入口处写一个if not xxx: return xxx的兜底成本极低效果极好。第二单元素输入。数组只有一个元素链表只有一个节点。很多算法在这种最小规模输入下会出问题尤其是涉及双指针和链表指针重连的时候。第三重复元素。数组里有大量重复值尤其是排序后很多去重逻辑都要在这个场景下验证。第四数据极值。整数最大值、最小值负数超长字符串。这些问题在Python里还好Python的int不限制大小但如果你用C或Javaint溢出是个不可忽视的隐患。处理边界条件的核心方法就一个设计用例的时候特意把边界情况作为第一优先级。不要只拿官方示例跑一遍就交那是最低标准不是合格标准。5.2 运行超时的排查思路运行超时(Time Limit Exceeded)是中等卷练习里最常见的问题之一。很多人一看到超时就慌其实排查思路完全可以标准化。第一步看数据范围。如果数据量是10^5级别而你用了O(n^2)算法超时是正常现象目标应该是把复杂度降到O(n log n)或O(n)。第二步检查是否有多余的循环。有些人会在循环里做重复计算比如每次都重新调用length()虽然是O(1)操作但放在大循环里也会积少成多。更常见的是原本可以用哈希表O(1)查找的地方却用了列表的in操作复杂度瞬间变成O(n)。第三步检查是否在递归里做了大量重复计算。如果是考虑用记忆化搜索或改成动态规划。第四步检查是不是死循环。这种情况虽然少但一旦出现判题系统也会报超时。比如双指针条件写反了left永远不大于right那就永远跳不出循环。这类问题用一个小数据集在本地跑一遍就能发现。我个人排查超时的习惯是先把代码里的核心循环打印出来统计一下循环执行了多少次。如果比预期多了一个数量级那基本就能锁定问题出在哪了。5.3 输出不对但逻辑正确先怀疑这三处还有一种气死人的情况代码逻辑怎么看都对测试用例也过了但提交就是WA(Wrong Answer)。这时候我会按下面的顺序检查类型问题。C/Java里int和long相乘会不会溢出浮点数比较有没有用等号这些都是隐蔽的类型坑。索引问题。Python的切片区间是左闭右开边界条件写错一两个位置结果就天差地别。比如left和right到底表示下标还是第几个元素这类语义混淆非常要命。排序稳定性问题。如果题目要求按原顺序输出而你用了不稳定排序最终结果可能就不对。这时候要用带索引的结构体或自定义排序规则。如果这三处都没问题那大概率是题目的某些隐含条件你没注意到。比如“不重复的三元组”里的“不重复”指什么是下标不重复还是数值不重复重新读一遍题目描述往往能找到答案。5.4 一份供直接上手的中等卷经典题清单根据我自己的练习经验和带人反馈下面这份清单覆盖了中等卷最常见的考点按由易到难的顺序排列。建议每道题都仔仔细细做一遍做完再对照总结序号题目标签代表题练习价值1数组/双指针三数之和双指针去重的标准模板2数组/滑动窗口无重复字符的最长子串滑动窗口入门第一题3链表/双指针反转链表II链表区间操作虚拟头节点4链表/快慢指针链表的中间节点快慢指针经典应用5哈希表字母异位词分组哈希映射分组6二叉树/DFS二叉树的最大深度递归基本功7二叉树/BFS二叉树的层序遍历队列BFS模板8二叉树/递归验证二叉搜索树区间递归子树关系9动态规划爬楼梯第一个状态转移方程10动态规划零钱兑换最值型DP入门11回溯全排列回溯算法的骨架12栈有效的括号栈的标准应用这份清单不是让你一口气刷完而是建议用它做“周例行检查”每周抽出固定时间挑两到三道做完之后把思路和代码整理到本地文件慢慢形成自己的题库。6. 初学者的进阶路线图中等卷之后的下一站在哪里如果你已经能稳定地解决中等卷的题目下一步的成长路线其实很清晰。我给三个方向供参考。第一个方向是“把经典题吃透”而不是继续追求题量。很多人刷题有个误区觉得刷得多就等于学得好。但中等卷真正有价值的不是“我又做出来一道”而是“我彻底搞懂了一种解法”。我见过一位朋友把“最长递增子序列”这一道题反复做了四遍每一遍都用不同的方法从动态规划到贪心加二分做完之后他对这类题的感觉得到了飞跃式提升。这叫“一题多解”。第二个方向是“为每一道题写总结”。刷完题之后用三五句话写清楚“为什么当时没想到”“题解里最关键的一步是什么”“下次见到什么特征可以联想到这个方法”。这个过程能帮你把短时记忆转化为长期能力。我自己的习惯是每题刷完后写一篇简短的复盘哪怕只有几行积累到一定量之后回头看成长轨迹特别清晰。第三个方向是“把算法和工程结合起来”。刷题刷到一定阶段很多人会问这些算法到底有什么用其实你在工程项目里用的缓存淘汰策略、日志聚合、任务调度、数据库索引设计背后都是这些基础数据结构和算法。到了这个阶段你可以尝试去读一些开源项目源码看它们是怎么把算法思想落地的。我个人对初学者的建议是中等卷不是终点。它是编程道路上的一条分水岭——跨过它你能写的就不再只是“能跑的代码”而是“有性能意识、有结构意识、有边界意识”的代码。这种意识会直接影响你未来参与真实项目的质量。最后再分享一个小技巧刷中等卷的时候给自己限定时间。拿到一道题先给自己20分钟独立思考哪怕想不出来也要把思路卡在哪一步记下来。然后再看题解。这种“先受阻、再看解”的方式比直接看题解有效得多因为你的大脑带着问题去看答案吸收效果完全不一样。
返回列表