跳至主要內容

 

labuladong原创约 5844 字大约 19 分钟

本站的效用

帮你练成框架化,模板化的思维方式解决算法题。如果满分 100 分,无论你的基础如何,本站都可以在最短的时间内帮你提升至 85 分的水平。

因为我教的是模板化、框架化的思维模式,所以你练成的这个 85 分是可以隔绝运气,稳定复现的。换句话说,难度小于 85 的题目,你一定能做出来,难度大于 85 的题目,才依赖你的灵感和运气。

对比参考一下 85 分是什么概念,假设你大学学计算机专业,上过学校开设的数据结构和算法必修课,工作中主要使用各种开发框架,从没刷过算法题,那么你的水平大概是 30~40 分。

所以不要觉得 85 分低,这个水平对于技术岗面试笔试绰绰够用了。当然,也不必畏惧算法,只要使用正确的方法专门花些时间刷题,算法水平提升起来也是很容易的。

谁适合学习

本站的教程老少皆宜,适合所有算法功力小于 85 分的读者阅读。因为绝大多数人刷算法是为了面试找工作,所以下面从校招和社招两类读者的角度讲讲本站为什么是性价比最高的选择。

对于校招的应届生,你按照我所说的方法修炼,从一开始就走对方向,可以巨幅提高效率,保你在大学期间玩也玩好,学也学好,俗称事业爱情双丰收(手动滑稽)。

说正经的,算法对校招非常重要,因为:你还没有工作,问不出什么正儿八经的项目经验,问你八股文吧,都是有标准答案的,玩不出什么花活,只有算法是唯一的变数,可以有比较大的考察空间。所以大厂校招都喜欢考算法,这东西很适合拿来筛选校招生。

那么很多同学就保持了中学时代的题海战术,天天刷题,但遇到新题还是不会,为什么呢?因为没有梳理出脉络呀,你刷一道题就只是刷一道题,难道你真要把题库里几千道题都做一遍背下来不成?

我就是来告诉你这个脉络的,让你刷一道顶十道,第零章那几个算法模板,你哪怕只看过一遍有个印象,未来总有一天你会恍然大悟,再回来翻看的。

还经常有应届同学问我,他想去打算法竞赛,适不适合学习这个教程

既然你来问,就说明你还是个新手,对吧?那当然适合你了。算法竞赛这个目标是更高一些,但你也要一步步来,俗称先盖了一楼二楼才能盖三楼对不对?你想挑战 95 分,我先给你蹭蹭蹭拔到 85 分,剩下的靠你自己再接再厉,这冲突吗?不冲突吧。

对于已经工作准备社招跳槽的读者,更需要我这种教程。对于应届生,即便走点弯路,但架不住人家时间多啊,哪怕是下笨功夫,也可以吭哧吭哧地修炼到 80 分的。

但是工作后可不一样了,就是要在有限资源内打出尽可能好的效果对不对,难道你真准备花大块的时间专门学算法啃大部头,刷几千道题?不现实,不划算,没有性价比。

对于社招,工作经验无疑是最重要的,大厂招人也考算法,但顶多也就考到 medium 的难度。所以嘛,我的教程保你迅速修炼到 85 分,绰绰够用了,剩下的时间用来刷刷简历,陪陪家人,都比在这个算法上耗着强。

接下来回答,为什么我的算法教程可以做到帮你短时间速成

中学时代,也见过那种每天认真听讲做笔记,依然考不好的同学吧?也见过那种天天上课睡大觉,但依然考得好的同学吧?其实学霸的秘密,不在于笔记记得有多工整,而在于「抽象能力」和「启发式学习方法」。

什么是抽象能力呢?譬如编程,一个父类可以产生若干子类,一个子类又可以有无数个实例化。如果你执迷于一个个实例化的细节,那完蛋了,即便背诵一千个实例化又能怎样呢,还有一万个等着你呢;如果你能从细节跳出来,透过实例化看到类,看到父类,看到超类,甚至看到整个系统,一万个实例化,在你眼里其实只是同一个,那自然可以以不变应万变,这就是抽象的力量。

本站的算法教程所强调的「框架思维」就是对算法问题的高度抽象,我会手把手教你从实例化中看到超类的影子,还给你写满了注释和案例,这样你就可以抓重点,避免在细节中迷失,效率自然就提高了。

什么是启发式学习方法呢?传统的普鲁士教育,是老师告诉你勾股定理在教材第几页,你背下来吧,明天要考。启发式学习是,你来,你自己研究一下直角三角形三边有啥关系,你找出来一个规律,给它命名屁股定理。回头翻开教材,发现原来有人已经总结过了,于是微笑默叹,真是英雄所见略同啊,连名字都只差一个字呢。

本站的文章都遵循启发式讲解方法,尤其是题目带有【强化练习】的习题章节,我会给出每道题目的解法,但是重点在于阐述我的思考过程,甚至包括一些错误的尝试。目的是启发你自己的思考,而不是仅仅给你展示一堆代码。

你们不是老是说自己拿到题没思路么?这就手把手展现给你思路是怎么来的。在前期,你可能会感觉这种启发式学习方法有些吃力,但很快就会收到超额的回报,大幅提升学习效率。

我有这个信心,无论思维模式上还是具体的代码细节上,大家都能从本站的算法教程中有货真价实的收获。

算法学习的五大坑

坑一:被误导,白白浪费时间

尤其是初学者,特别容易被别人有意无意地灌输了错误的思想。以为算法很高大上,非要有很好的数学基础,非要啃完算法导论才算是入门,所以从心理上就畏惧算法。

我对这个问题有切身体会,刚学算法那会儿,我会去搜索过各种资料、经验贴之类的,我就记得很多所谓「大佬」,你问他怎么入门算法,他告诉你看《算法导论》,然后又甩给你一堆英文课程,还强调一定要看英文的哦,中文的翻译不好。

这就好比,你是一个胖子,去问人家怎么减肥,人家告诉你,每天做 100 个俯卧撑,200 个引体向上,肯定有效,你看我就是这样练出来的!

呵呵,我要是真能做到这些,还用得着来问么?不过仔细琢磨琢磨,给出这种回答是基于一种什么心理?实际上他根本不在乎你的诉求,他只是想告诉你:我做过这些,我牛逼吧,我厉害吧,你羡慕吧,你做不到吧~

算法导论是不是好书?是。它讲的内容硬不硬?硬。但对大多数人求职找工作有没有用?没啥用,性价比太低了。

什么性价比高?直接刷题。正确的刷题方法我后面会讲,但首先你方向要明确,只有刷题是正道,其他的都是辅助手段。如果这个学一点,那个学一点,感觉懂了很多,但最后一笔试发现啥都用不到,傻眼了,找谁说理去?

在本站的教程中,第零章的开篇,直接给你论证算法的本质是穷举,简单粗暴,做算法题从这个角度切入就对了。按照本站总结的方法刷题,很快就能把穷举玩明白,一般的笔试随便你杀个七进七出,这真的不是吹牛哦。

坑二:贪多,贪巧

何谓「贪多」?有些读者可能陷入到追求量的陷阱里。比如我看到一些培训机构,说自己的图文资料有几万页,视频资料有几百小时几百 G,甚至还把量大作为自己的优势进行标榜,这说明肯定是有部分读者好这口。

在我看来,量多不是优势,反而是劣势。咱就实话实说,哪怕这几百 G 的资料真的不错,你会花那个时间和耐心去看,还是放到收藏夹吃灰?

为了帮读者提高学习效率,我一直在优化和精简本站内容,并且把算法的所有奥妙都总结到了本站第零章:

对于有一定算法功力的读者,看完第零章如果有恍然大悟之感,那么本站其他内容你不看也无妨。因为剩下的内容只是把同一套方法重复了一百遍,其目的是为了手把手带着初次接触算法的读者在一次次重复中掌握这套方法。

对于初学者,按照本站目录顺序学习即可。虽然第零章把最核心的东西告诉你了,但是你有个印象即可,不可能完全理解的。需要后面的章节给你一遍遍展示如何使用,以及你自己在做题中思考实践,才能真正让你做到知行合一。

所以我给初学者的建议是,沉下心来,要有耐心。虽然我在开头说能让你速成,但速成的前提是科学正确的方法叠加持之以恒的专注力,我可以提供前者,后者需要你的努力。

何谓「贪巧」?大家肯定会被力扣评论区里面一些大佬的精彩解法吸引,但是我想说,在培养出自己的框架思维之前,不必追求一题多解

那些解法帅不帅?帅。有没有用?那要看你是什么水平,如果你已经达到 90 分以上了,那随便你,你怎么写都可以写对。但如果你的水平还在四五十分徘徊,那咱就聚焦关键问题,老老实实蹲马步练基本功,老想着抖机灵就舍本逐末了。

你学到后面就能体会到了,大道至简,算法就是穷举,本站的全部内容都是围绕这两个字。大部分情况下,你按照框架写代码,逢山开路遇水搭桥,见招拆招逐步优化,最后写出来的就是最优解,和那些花哨的算法效率是相同的,你以不变应万变,何乐而不为呢?

坑三:刷题没有章法

明确了主要方法是刷题,那么接下来的坑是:刷题没有章法,乱刷一通,胡子眉毛一把抓。力扣上几千道题,你是准备全部刷完背下来么?

我不否认大力可以出奇迹,比方说你如果真能刷个一千道题,你肯定会有一些感觉的。但问题是,我有一妙法,可以让你刷一道顶十道,你想不想学呀?想吧,其实很简单,刷题不要贪数量,而是要归纳总结,高度抽象,最终目标是培养出自己的框架思维。

说白了,那么多算法题,大多都是换汤不换药,你把药方记住了,汤换来换去,你都是照方抓药,不是么?

第零章就是所有常见算法的代码框架汇总(药方),这部分内容初学者看起来会有些吃力,没关系,实在不理解可以跳过,后面的所有文章以及习题都是围绕这些算法框架展开的,我给你把相同的套路手把手演示 100 遍,岂有学不会之理?

按照本站的目录顺序学习,就可以循序渐进掌握所有常见算法技巧,完成 500 道力扣/LeetCode 题目,培养出你自己成体系的框架思维

为啥我这么强调这个框架思维?因为它可以从根本上解决你遇到新题无从下手的问题。

比方说吧,如果你掌握了框架思维,现在随便给你一道题目,那你就可以按照固定的思维步骤进行思考:

这题让我们干什么?奥,让我们操作字符串。字符串本质就是个数组,所以这题考察的大概是数组相关的算法技巧。

数组有什么算法技巧?你心里有数,无非就是 二分查找快慢指针左右指针滑动窗口前缀和数组差分数组,主要就这些。

二分查找的适用场景是什么?差分数组的适用场景是什么?你挨个想一遍,这个不行换那个,总能试出来个相对靠谱的吧?

好,比方说你最后感觉这个题用滑动窗口比较靠谱,那么换一般人,你告诉他这是滑动窗口,他大概率半天憋不出来一行代码。但你不一样,你知道滑动窗口的代码框架,所以你是先把框架写出来,然后往框架里面填充代码。

如何填充?简单啊,滑动窗口核心框架 总结过了,用滑动窗口要自问三个问题,你回答一下这三个问题,然后这个题就写完了,提交代码一遍过。爽不爽?

爽吧,那我再给你 100 道滑动窗口题目,你都按完全相同的套路,改点细节就都解决了。这时候,你觉得算法还难么?

坑四:对递归理解不透彻

前面一系列坑你都不掉进去,我们最后才探讨技术性的问题。很多读者说,动态规划,回溯算法,这类递归算法,他完全写不出来。

那是,如果你光盯着代码看,肯定不好写。关键在于你心中是否有一棵递归树,那棵树出来了,你的代码就写出来了。

所以以我的刷题经验,初学者最好从「树」相关的问题开始练习递归思维,为此我特意写了 手把手刷二叉树(纲领篇),帮你从二叉树的视角理解各种复杂的递归算法。在 二叉树专项训练章节 从二叉树这种基本数据结构入手,推广到动态规划、回溯算法等常见递归算法中,手把手带你做 200 道习题,保你能随心所欲地写出递归代码。

另外,我开发的算法可视化面板专门对递归算法做了加强。比方说这是个普通的递归函数,但是你可以看到它的递归过程被可视化成了一棵递归树,鼠标移动到树的节点上,还会弹出递归路径上所做的选择:

可视化面板的具体用法可以参见 可视化编辑器简介,这里仅仅做个展示,就不细说了。

本站的实用功能

1. 代码图片注释

比如有些较为复杂的代码块中包含小灯泡图标,鼠标移至小灯泡图标上就会弹出图片辅助理解,比如 双指针技巧秒杀七道链表题目 中这段解法的代码:

java 🟢
class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast, slow;
        fast = slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) break;/**<extend down -200><div class="img-content"><img src="/algo/images/双指针/3.jpeg" class="myimage"/></div> */
        }
        // 上面的代码类似 hasCycle 函数
        if (fast == null || fast.next == null) {
            // fast 遇到空指针说明没有环
            return null;
        }

        // 重新指向头结点
        slow = head;/**<extend up -100><div class="img-content"><img src="/algo/images/双指针/2.jpeg" class="myimage"/></div> */
        // 快慢指针同步前进,相交点就是环起点
        while (slow != fast) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

2. 支持算法可视化动画

我集成了一套算法执行过程的可视化工具,你可以直接在网页上看到算法的执行过程,辅助理解算法逻辑。

比如这个判断单链表环起点的算法,链表的操作过程被可视化出来,而且这个面板是可以交互的哦,你可以点击代码中的某一行,面板就会跳转到对应的执行步骤,每一步执行的代码都会高亮显示:

可视化面板对递归算法可视化有特殊的加强,具体的介绍请看 可视化面板简介,手把手教你如何利用可视化面板理解复杂算法。

3. 支持阅读历史

在侧边栏中,学完的文章会显示 标记,未学完文章会显示 标记,方便你了解自己的学习进度。

4. 内容互相引用,融会贯通

我在每篇文章末尾添加了该文章相关的其他文章及其他算法题,你点击链接就可以跳转过去。这是 BFS 框架详解 文末的例子:


引用本文的文章

而且结合我的 Chrome 刷题插件,点击相关题目可以直接显示 Chrome 插件中的思路解析,无缝衔接。

5. 支持所有主流编程语言

老读者都知道,以前我的算法教程主要使用 Java 语言。但是现在,我的网站已经支持了 Java/C++/Python/Golang/JavaScript 等所有常用的编程语言(代码块上有 tab 可以切换),能尽可能照顾到更多读者的需求。目前只有最终解法或者比较重要的代码片段才会提供多语言的支持,一些伪码片段或者逻辑比较简单的代码片段一眼就能看懂,就没什么必要提供多语言版本了。

需要注意的是,带有 🟢 标记的是我写的代码(大多是 Java 语言),带有 🤖 标记的其他语言解法代码是利用 chatGPT 生成的,旨在帮助不同背景的读者理解算法逻辑。这些代码经过我手工调试后准确度已经非常高了,不过不排除还会有出错的情况。如遇到错误请大家多多包涵并在 这里open in new window 反馈或修复。

为了做到循序渐进,我的文章中的解法代码可能是一部分一部分给出的,所以为了清晰简洁,有些代码片段我会适度变通。比如力扣一般是让你把解法代码写在 Solution 类的一个类方法里,而我经常会省略这个类,直接把解法逻辑写在一个函数中。那么像 Python 的解法,正常来说类方法的第一个参数必须是 self,而我写成普通函数的话就会省略掉这个参数。

所以有时候需要你在我给出的代码上稍作修改,改为符合力扣的提交格式,才能通过力扣的测试用例。当然,我的系列刷题插件中给出的都是完整解法,可以一键复制粘贴(如果你想的话)。

提示

这体验够不够丝滑?除了本站,最新版的 Chrome 插件、vscode 插件、JetBrains 插件与本站同步,全都拥有上述实用功能

6. 文末讨论区,我会定期查看

我在每篇文章下都开放了评论区,欢迎大家友好讨论。点赞是一种态度,如果有的评论帮助到了你,请不要吝惜你的点赞。如果你想评论,请注意遵守基本礼仪,禁止嘲讽、阴阳怪气、刷屏、发学习无关的内容。我会定期查看并回复评论,发现违规者直接拉黑,希望大家共同维护良好的学习氛围。

很多读者留言说我快把那些算法培训班干失业了,这话我可不敢当,大家能从我这学到东西我就很高兴,不差钱的买个 我的网站会员 捧个钱场,缺钱的把我推荐给身边的朋友捧个人场,都是对我的支持,真心谢谢大家!

7、刷题全家桶全方位辅助学习

「labuladong 的刷题全家桶」由学习网站(本站)、算法可视化工具、Chrome/vscode/Jetbrain 三个不同平台的刷题插件组成,致力于为大家提供最丝滑的刷题体验,帮助大家高效学习算法。

该有的我全都给你准备好了,请自行选择合适自己的工具。具体介绍安装使用方法我会在第一章详细介绍,左右滑动幻灯片可查看简介:

本网站结合配套插件,目前可以手把手辅助你用本站的总结框架思维解决 600 多道算法问题,全部都是基于力扣的题目,涵盖了所有题型和技巧。

我已经把在每篇文章的开头加上了该文章可以解决的题目链接,可以看完文章立即去拿下对应题目。而且我还在不断优化、精简内容,致力于打造最好的算法教程。

上次编辑于: