1. 先从标题说起:为什么叫“每日一练壹”
“每日一练壹”这个标题乍一看很简单,拆开无非是“每天”+“练习”+“壹”。但做练习这件事,绝大多数人败就败在“每天”这两个字上。我见过太多人,初期热情高涨,立下flag,结果坚持不到两周就断了。原因倒不是懒,而是根本没有建立起一个能对抗“遗忘曲线”和“疲劳期”的练习机制。
我把它命名为“壹”,有两点考虑。第一,代表“只做一件事”:每天只练一个核心点,不贪多,不浅尝辄止。第二,代表“从头开始”:不管今天是第1天还是第365天,每次练习都把自己当作初学者,拆解每一个细节。这个思路适用于很多领域,但我目前主要实践在编程算法练习上,下面分享的具体方法和踩坑经验也偏技术向,如果你在练的是其他技能,换个皮就能用。
这个练习计划适合谁?适合那些不知道每天该练什么、练了没效果、坚持不下来的人,尤其是准备面试的程序员、刚入行想打基础的新人,以及想摆脱“只刷题不总结”状态的进阶选手。我对这套方法的核心要求只有一个:可执行。再好的计划,如果做不到,就是废纸。
2. 整体设计思路:练习不是堆量,是建立反馈回路
2.1 一个核心公式:练习效果 = 题量 × 反思深度 × 间隔次数
很多人以为“每日一练”等于每天刷一道新题,这是一大误区。真正让练习生效的是一个反馈回路:投入时间做题 → 发现错误或卡壳 → 分析错因 → 修正认知 → 间隔一定时间后再来一次。
我用一个公式来概括:练习效果 = 题量 × 反思深度 × 间隔次数。注意,这三个变量是相乘的关系,任何一个为0,结果就是0。哪怕你每天做十道题,但从不回头看错题,反思深度可视为0,练了等于白练。反过来,如果一周只做一道题,但反复琢磨、隔几天就重做一遍,吸收效率反而可能更高。
所以“每日一练壹”的题量要求很低,一天一道新题加一道复习题,总共两道。新题是探索未知边界,复习题是巩固已有认知。记住,复习不是简单地再做一遍,而是隔两天后重新独立写出解法,写不出来就说明上次根本没学会。
2.2 为什么不是每天刷五道题
初期我也试过“一天五道题”疯狂刷题模式,坚持了几天,心态崩了。主要原因有三点:
- 脑子消化不了。人的工作记忆容量有限,一天塞进来太多解法结构,第二天就会互相干扰,比如混淆二分查找边界条件、忘了滑动窗口的状态更新逻辑。
- 产生心理抵触。每天一想到还有四道题没做完,就本能地拖延,最后一道都没做。
- 没有复盘时间。五道题做完已经深夜,哪还有精力写总结?而没有总结的练习,就像不过筛子打谷子,粮食和糠壳混在一起,看似收获大,实际留存极少。
后来我把目标从“每天五题”换成“每天一道做完、一道复习、一篇总结”,效果反而明显提升。面试时机考基本功,考察的不是你做过多少题,而是你在限时压力下能不能把一道题的思路想清楚、写干净。
3. 题目选择与分级策略
3.1 三种选题来源:按场景灵活切换
每天练什么题,比练多少题更重要。我按来源把题目分成三类,交叉着用:
| 来源类型 | 特点 | 使用场景 |
|---|---|---|
| 面试高频题库 | 覆盖主流考点,题目质量高 | 面试冲刺期,按频率降序刷 |
| 专题分类题库 | 按数据结构/算法分类,知识点密集 | 打基础期,按专题逐个攻克 |
| 随机/每日推荐 | 可能遇到陌生题型,锻炼临场分析能力 | 保持期,防止知识面固化 |
这三种来源对应不同阶段。刚开始学习,必须用专题题库,因为同一类题连着做,你才有机会总结出套路。比如连续做十道“括号匹配”相关的题,你才能深刻理解栈的进出栈时机。如果今天一道栈、明天一道动态规划、后天一道图论,大概率每道题都做不出来,挫败感还会特别强。
面试前两到三周,主攻高频题,每天新题加三道高频重做。我不建议在这个阶段刷冷门题,性价比太低。面试官出的题大概率分布在最热门的几十道题里,哪怕题目有变体,核心思路依然是那些最高频的模型:BFS/DFS、双指针、前缀和、动态规划、二分、贪心。
3.2 难度曲线的控制技巧
我推荐遵循“85%熟悉度 + 15%挑战”的配比。每天的新题里,大部分应该是你垫垫脚就能够到的难度,而不是让你完全崩溃的五星难题。判断方式很简单:拿到题5分钟,只有零散思路但不知道怎么落地 —— 这道题难度刚好。如果5分钟完全没头绪,看懂答案都很费劲,说明太难,先放着,等过一两周再回来挑战。
连续三次选择过难的题目,练习热情会迅速归零。我在实践中总结过一个简单经验:如果一道题你第一次做需要看答案才能写出来,三天后重做依然需要看答案,就说明它超出现有水平太多。不要跟它死磕,果断降低难度,先把大脑里的基础算法模型建好。能力提升不是靠氧气面罩憋气,而是靠每天适度拉伸。
4. 每日练习的标准流程:五步法
4.1 从读题到提交,每个环节都有明确动作
我给自己规定的流程如下,每一步都有产出,不会漫无目的地磨时间:
- 读题并手写要点(2分钟):在纸上写下题目类型、输入规模、主要约束条件、输入输出示例。这一步逼你认真看题,避免漏掉关键条件。
- 口头讲思路(3分钟):假装有人在旁边听,用自己的话描述解法思路,比如“我先排序,再用双指针从两端向中间逼近,注意到数组里有重复元素,要去重”。讲不顺畅的地方就是没想通的地方,标出来。
- 写代码(15到25分钟):严格按讲好的思路写,边写边说明每一个关键步骤。不要在没想清楚前就动手敲代码,不然二十行以后必然逻辑混乱。
- 运行和检查(5分钟):先跑示例用例,再用边界值测试,比如空数组、只有一个元素、全部相同元素、溢出边界值等。
- 复盘提交(10分钟):写总结,记录方法名称、时间空间复杂度、一两个关键记忆点、卡壳原因。
步骤3里我特别强调不要提前动代码,因为很多犯的错不是语法错误,而是步骤拆分混乱。口语梳理思路时,你会自然把问题拆分成了几个子步骤,代码写起来就是照着顺序填空。动键盘前先想清楚,这是解决“改了半天还不知道逻辑错在哪”最有效的手段。
4.2 每道题的复盘笔记怎么记
复盘笔记的质量,直接决定一周后重做时你能吸收多少。我用的格式固定,非常简洁:
- 题目名称与链接
- 考点标签(如:哈希表、双指针、区间合并)
- 我的首次解法与实际耗时
- 最优解的思路与复杂度对比
- 卡壳点回顾(具体到哪一行代码、哪个边界条件没想明白)
- 一句话总结规律(比如“遇到区间相交问题,先按起始位置排序”)
记录时注意:不要大段抄题目解法,而是记“从题目到答案的思维链”。比如记录“我没想到可以用前缀和预处理查询区间和”比记录“前缀和公式是 pref[i] = pref[i-1] + nums[i]”有用得多。前者是思维的缺口,后者随时能查资料。
5. 核心环节实操:一个二分查找的完整复盘案例
5.1 我第一天练的题是什么样的
拿我练的第一道题举例:标准二分查找。给出一个升序数组和一个目标值,返回目标值的下标,不存在则返回 -1。看起来简单,实际有不少隐形陷阱。第一次做时我栽在“循环结束条件”上,用的是 left <= right 还是 left < right,没想清楚就开写,写完调了半天。
现在我把这道题拆解一下,你可以看看一个系统的练习者是带着什么眼光看一道基础题的:
- 边界条件:目标值比数组最小值还小,或比最大值还大,循环结束时 left 和 right 的位置在哪里,返回值应该是什么。
- 循环不变量:我维护的是“搜索区间”,当 left > right 时区间为空,此时才退出循环。这个认知要内化,不是背模板。
- 中间值计算:mid = left + (right - left) / 2,写成 (left + right) / 2 可能在极端大数下溢出,虽然刷题环境一般不会触发,但好习惯从开始就养成。
5.2 一个二分的模板变体
// 找第一个 >= target 的位置(lower_bound 的实现思想) int lowerBound(vector<int>& nums, int target) { int left = 0, right = nums.size(); // 注意 right 是开区间 while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < target) { left = mid + 1; // mid 位置不满足,排除掉 } else { right = mid; // mid 可能是答案,保留右区间 } } return left; // 或 right,此时 left == right }这个模板的关键在于:把条件判断为“排除法”,而不是“找到答案”。当前 mid 不满足条件,就把这一半删掉;满足条件,就收紧右边界继续找更靠前的。学会这套思维方式,遇到“找第一个坏的版本”“寻找峰值”这类二分变体题时,套用排除法就很顺畅。如果只是死记模板,题目条件一变就懵。
5.3 时间成本核算:一天到底投资多少分钟
入口寸金难买寸光阴,很多人都关心练这个到底耗时多少。我实测的平均值如下:
| 环节 | 新手耗时 | 熟练后耗时 |
|---|---|---|
| 读题与手写要点 | 3分钟 | 2分钟 |
| 口头讲思路 | 3分钟 | 2分钟 |
| 写代码 | 25分钟 | 15分钟 |
| 运行与边界测试 | 5分钟 | 3分钟 |
| 复盘笔记 | 10分钟 | 5分钟 |
| 复习旧题一道 | 10分钟 | 6分钟 |
| 合计 | 约56分钟 | 约33分钟 |
加上每天那两道题的思考间隙,最多不超过1小时,完全在大脑耐受范围内。如果你当前基础较弱,写代码环节可能超过30分钟,那就只做新题,复习并入第二天,不要硬撑。关键是执行完整流程,而不是追求一次完成的数量。
6. 实操中遇到的常见问题与排查思路
6.1 坚持了两周,看不到进步怎么办
这是几乎所有人都会经历的阶段,我自己也没能幸免。头两周做的题也不少,但到了第三周做新题时,感觉自己还是“不会”。排查后发现,问题出在记忆曲线上的盲区。当时我只做新题,没有安排复习,第一周做的题,到第二周已经大半完了,等于做的题都随着记忆流失了。
调整方式:每周抽三天,只做旧题重写。不是凭记忆默写,而是像第一次做那样,在白纸上画图推导,重新跑通逻辑。这一步做完之后,到第四周我再看同样的题,心虚感明显下降。没有间隔重复的练习,就像用破了的水桶打水,打多少漏多少。
6.2 遇到一道题,完全没有思路怎么办
这个问题很常见,我现在的处理方式是给自己设定“15分钟观察期”,而不是和题目死磕。观察期内做的事是:
- 列输入输出的关系,画几个小例子手动跑一遍
- 问自己三个递进问题:这个问题的暴力解法是什么?暴力解法里有哪些重复计算?能不能用空间换时间?
- 把题目跟已学专题对照:“这和前缀和有什么关系?”“能不能排序后双指针?”“是不是可以二分?”
15分钟一到,如果依然没有思路,直接看题解。但看题解有讲究:不要只看代码,先只看思路提示,比如“用单调栈维护最近更大元素”,合上题解自己写。如果这还写不出来,再看代码,看完合上,纯手写一遍。这跟学弹琴一样:看着谱子弹十遍,不如背谱弹一遍记忆深刻。
6.3 复习旧题时,发现完全忘了怎么做
正常。忘了,恰恰说明当时的复习安排没到位。我碰到这种情形不会自责,反而把它当成一次可贵的暴露问题机会。处理方式:先不翻题解,按新题的流程重推一遍。能推出,说明解题肌肉还在;推不出,就重新做一遍并延长复习间隔安排。整个过程心态要放松,练习本来就是螺旋式上升的,前一天的“会”可能是假会,今天暴露了反而是赚到。
6.4 碎片时间怎么用,每天的大块时间不够
如果你是学生或上班族,很难每天都找到完整一小时的整块时间。我的做法是:把流程拆成微功能块,穿插在碎片时间里。午休花10分钟读题并手写要点,下班路上15分钟讲思路,晚上回家花25分钟写代码和测试,睡前10分钟复盘。只要保证当天完成的是“完整闭环”,环节间有间歇没关系。但注意,至少写代码和测试两个环节必须在一起,中间隔太久思路断了,浪费的是自己的时间。
6.5 练习平台选择与评测对抗
市面上的刷题平台,我试过不少,最终留下一个主用的和一个备用的。主用的用来做每日练习,因为它有每日推荐和题解讨论区,解题后能看到别人更简洁的解法,复盘时能产生对比,促进思考。备用的用来做竞赛周赛,因为它社区氛围好,偶尔打一场周赛能检验这周的练习成果。评测平台不是越贵越好,要选顺手、题目质量高、评论区有干货的。一个平台的题目如果太偏、太怪,不值得花时间,刷题的主要目的是建立通用能力,不是收集稀奇古怪的题目。
7. 一些容易忽略但很重要的执行细节
7.1 选题库顺序的“先打框架,再钻细节”原则
前面说不同阶段用不同来源,但一个基础原则是:先打框架,再钻细节。我按这个顺序过专题:数组与链表 → 栈与队列 → 哈希表 → 树 → 图 → 排序与搜索 → 动态规划 → 贪心。每个专题不必完全掌握所有的题再进下一个,那会拖慢进度。我的建议是:每个专题先做够20道经典题,能把常见套路讲出来,就进入下一个。框架先搭起来,后面再做新题时,你会发现自己能调用更多已学知识,交叉思考的能力也在悄悄长进。
7.2 写代码的书写规范与边界测试清单
每天练习时的一丢丢好习惯,会在以后节省很多时间。我整理了一份自己的边界测试清单:
- 空输入或空数组
- 只有一个元素的输入
- 所有元素相同的输入
- 输入已经有序或完全逆序
- 目标值不存在于数据中
- 数值达到题目给定的最大最小值
每次提交前,对照这些条件在心里或草稿纸上跑一遍,能拦截约四成的逻辑错误。不要依赖评测系统的报错,尤其是面试场景,没有反馈的机会。手写代码之前,先用这组边界条件验证自己的思路方向,比写完再反复调试高效得多。
7.3 休息怎么安排
每日一练不等于禁止休息。我的安排是每周练六天,留一天完全休息不碰题。持续紧绷跟持续松懈一样有害。每周的休息日实际上让大脑有机会把过去一周的练习巩固下来,大脑在睡眠和休息状态下会重放激活过的神经回路。另一件休息日该做的事是浏览一些经典题的题解讨论区,不写代码,只读思路,相当于给下周的练习做个预加载。
8. 一些更长远的问题:练到什么时候才算练成
这个问题我被问过很多次。老实说,练成没有绝对标准,但我自己心里有一些可测量的信号:
- 看到一道中等题,能在两分钟内定位考点,并给出大体复杂度可接受的解法。
- 高频题里,能独立完成率超过八成。
- 写代码时很少因为边界条件或循环条件返工。
- 能在规定时间内把思路完整讲清楚,相当于面试状态。
达到这四个信号,基本说明练习体系已经生效,可以进入到“保持期”,每周练两三次维持手感即可,不必再每天投入一小时。如果目标是顶级大厂面试,那需要加大难度和系统性,但这是后话。
这套练习方法我实际用了大半年,从最初每天硬着头皮跑完全流程,到后来形成条件反射,最大的感受是:真正改变人的不是某一天的爆发,而是每一天的小推进。把“每日一练”变成一个跟刷牙一样自然的动作,回头算总账时,那个数字会吓你一跳。
最后分享一个小技巧:准备一个实体笔记本,每练一天就打一个勾,连续断了就画一个叉。不要小看这个行为,触手可及的视觉反馈比手机App上的打卡更能抵抗放弃的念头。本子上记录清晰,就算中断了,翻一翻还能找回手感,知道自己断在哪、为什么断,下次再启动时就不会无从下手。