本站简介
本站效用
帮你练成框架化,模板化的思维方式解决算法题。如果满分 100 分,无论你的基础如何,本站都可以在最短的时间内帮你提升至 85 分的水平。
因为本站教的是模板化、框架化的思维模式,所以你练成的这个 85 分是可以隔绝运气,稳定复现的。换句话说,难度小于 85 的题目,你一定能做出来,难度大于 85 的题目,才依赖灵感和运气。
85 分是什么概念?
对比参考一下,假设你大学学计算机专业,上过学校开设的数据结构和算法必修课,工作中主要使用各种开发框架,从没刷过算法题,那么你的水平大概是 30~40 分。真的是这样,因为算法这个东西可以理解为一种独立的能力,和编程经验没有直接的关系,需要专门花时间练习。
所以不要觉得 85 分低,这个水平对于技术岗面试笔试绰绰够用了。当然,也不必畏惧算法,只要使用正确的方法专门花些时间刷题,算法水平提升起来也是很容易的。
本站目录结构
本站简介
配套工具:刷题全家桶
针对初学和速成的学习规划
入门:编程语言基础及练习
基础:数据结构及排序精讲
手把手带你实现动态数组
手把手带你实现单/双链表
手把手带你实现队列/栈
哈希表的原理及实现
哈希表结构的种种变换
二叉树结构及遍历
二叉树结构的种种变换
图论数据结构及遍历
十大排序算法原理及可视化
正在更新 ing
第零章、核心刷题框架汇总
本章导读 学习数据结构和算法的框架思维 双指针技巧秒杀七道链表题目 双指针技巧秒杀七道数组题目 滑动窗口算法核心代码模板 二分搜索算法核心代码模板 动态规划解题套路框架 回溯算法解题套路框架 BFS 算法解题套路框架 二叉树系列算法核心纲领 回溯算法秒杀所有排列/组合/子集问题 算法时空复杂度分析实用指南
第一章、经典数据结构算法
手把手刷链表算法
手把手刷数组算法
手把手刷二叉树算法
套模板解决 100 道二叉树习题
二叉树的拓展延伸
手把手设计数据结构
队列实现栈以及栈实现队列 【强化练习】栈的经典习题 【强化练习】括号类问题汇总 【强化练习】队列的经典习题 单调栈算法模板解决三道例题 【强化练习】单调栈的几种变体及经典习题 单调队列结构解决滑动窗口问题 【强化练习】单调队列的通用实现及经典习题 算法就像搭乐高:手撸 LRU 算法 算法就像搭乐高:手撸 LFU 算法 常数时间删除/查找数组中的任意元素 【强化练习】哈希表更多习题 【强化练习】优先级队列经典习题 TreeMap/TreeSet 代码实现 Trie/字典树/前缀树代码实现 【强化练习】Trie 树算法习题 设计朋友圈时间线功能 设计考场座位分配算法 【强化练习】更多经典设计习题 拓展:如何实现一个计算器 拓展:两个二叉堆实现中位数算法 拓展:数组去重问题(困难版)
手把手刷图算法
第二章、经典暴力搜索算法
DFS/回溯算法
BFS 算法
第三章、经典动态规划算法
动态规划基本技巧
子序列类型问题
背包类型问题
用动态规划玩游戏
贪心类型问题
第四章、其他常见算法技巧
数学运算技巧
经典面试题
附录
阅读方法
对于时间紧急临阵磨枪的读者(准备时间 < 30 天),可以按照 速成学习计划 中的顺序学习。
对于有一定基础的读者(刷题量 > 300),第零章的内容必读,其他章节可以根据需求自行选择。
对于初学者,按照本站目录顺序阅读,稳扎稳打即可。本站同时适配 PC 端和移动端:
本站内容
本站主要有三种文章类型:
1️⃣ 数据结构基础教程(约占本站全部内容的 10%)
主要集中在 数据结构及排序精讲
这一章。这部分内容讲解排序算法以及经典数据结构的核心原理和代码实现,一般不包含算法题,主要目的是让读者了解工作中常用数据结构的原理,以及算法题中特有数据结构的原理及使用场景,未来做题时可以直接套用。
2️⃣ 结合例题讲解经典算法框架(约占本站全部内容的 50%)
一些比较经典的算法框架或算法题,我会用整篇文章结合具体的例题做比较细致的讲解,目的是让你理解原理。一般每篇文章包含 2~5 道例题,阅读时顺手就能做掉。
3️⃣ 习题章节帮你熟练运用算法框架(约占本站全部内容的 40%)
目录中标有【强化练习】
的内容属于习题部分,一般紧跟在算法框架内容的后面。习题都是可以直接套框架的题目,目的是通过大量的重复帮你练出肌肉记忆,彻底掌握一类题型的解法。每篇强化练习包含 10 道左右的习题,掌握算法框架后可以较快解决。
本站可以带你解决 500+ 道力扣公开免费的题目。这些题目中大部分都是用来练习框架思维的,只要掌握了几个核心的算法框架,几分钟就能解决,不知不觉中这些题目都能做完。
关于本站
认准本站的最新地址,持续更新:labuladong.online
本站同时支持手机、PC 阅读,手机端建议直接在微信内打开,方便一键登陆。
本站可以用框架思维手把手带你解决 LeetCode/力扣 500 道以上的题目,且训练出的算法思维不会退化,多年之后也能快速重拾解题能力。
点击本站右上角的放大镜图标可以搜索本站内容,支持直接搜索 LeetCode/力扣 的中英文题目、题号、链接。
本站在持续更新和优化,顶部有「更新日志」和「bug 反馈」入口。
已过期的网址/PDF/内容
由于我在不断更新、优化、修正算法教程,一些历史遗留的内容、网站都应该被废弃,因为现在有更简洁、优质的内容提供给你学习。
我在网络上其他平台发表的算法教程都已经过时,不再更新。
我曾经使用过的网站地址已经不再维护,包括:
曾经的 PDF 也已经过时,包括:《labuladong 的算法小抄》《labuladong 的刷题笔记》《labuladong 的算法秘籍》等。
力扣/LeetCode 题单
应部分读者的要求,我整理了一份题单,汇总了本站讲解过的所有题目。
但是请注意,我个人觉得这个题单用处不大,也不建议你直接对着这个题单刷题。
因为题单里面的题目是随机排序的,没办法做到循序渐进地学习,也没办法对某个知识点针对性学习。而且并不需要你真的把这么多题全部做完。
我会更建议你按照本站目录顺序学习,文中提到的例题,你顺手做一做就行了。题单中大部分都是习题章节的框架题,用来帮你训练框架思维的,掌握核心算法框架后可以直接秒,不需要刻意去刷。
这个题单唯一的作用也许是证明我没吹牛,本站确实可以带你用算法框架解决 500 道以上的题目。安装 Chrome 刷题插件 后点开这个题单,可以看到所有题目都有我的题解/思路标记,即这些题目都是本站教程覆盖到的。
力扣 | LeetCode |
---|---|
https://leetcode.cn/problem-list/59jEaTgw/ | https://leetcode.com/list/9zwo3ww5/ |
根据读者的反馈,这里再强调一个误区:题单不是重点,成体系的知识框架才是重点。
哪怕给你历年的考试真题,如果你心中没有各种算法的框架思维,那就只能沦为背题了,没用的。
题目稍微变一点,你肯定搞不定,因为掌握常见算法的框架思维是能够举一反三的前提。
所以我的建议是反过来,你先把常见的算法框架学明白,下一步,再考虑要不要看一看历年真题。到那时候,哪个题单你都会,没多大区别的,花两个小时就看完了。
本站的重点一直都在核心算法框架的教学上,习题的重点是帮你内化算法框架,确保你在未来遇到同类的新题时也能独立求解。
关于作者
我是 fucking-algorithm 仓库的作者 labuladong,读者一般叫我「东哥」,首创框架思维解题,多次霸榜 GitHub Trending,目前已获得 125k star。
我致力于做最好的算法教程,专注小而精,不做大而全;力争让读者在最短的时间内,彻底拿下算法这个硬骨头。
本站会员 为本站唯一的付费项目,一顿饭钱,即可解锁本站所有内容和所有配套工具,享受最丝滑流畅的学习体验。
本站实用功能
1. 支持算法可视化动画
在本站以及所有配套插件中,所有解法代码下方都配了一套算法可视化面板,可以直观地查看算法执行过程,辅助理解算法逻辑。
可视化面板可以大幅降低你对复杂算法的理解成本,支持所有数据结构和算法,这里仅展示几个例子。更多的经典算法可视化可以在 算法可视化速查页 中查看。
2. 支持阅读历史
在侧边栏和所有文章内,未读过的文章链接前面会显示
阅读数据会自动同步到所有设备。
3. 支持所有主流编程语言
本站和所有配套插件的所有题解代码都支持了 Java/C++/Python/Golang/JavaScript 等所有常用的编程语言,能尽可能照顾到更多读者的需求。
Java 代码都是我写的,其他语言的代码由 chatGPT 辅助翻译,但都经过了我的亲自验证和调试,确保正确性和一致性。
4. 代码图片注释
本站和所有配套插件中,对于较为复杂的代码块中会包含小灯泡图标,鼠标移至小灯泡图标上就会弹出图片辅助理解:
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;
}
// 上面的代码类似 hasCycle 函数
if (fast == null || fast.next == null) {
// fast 遇到空指针说明没有环
return null;
}
// 重新指向头结点
slow = head;
// 快慢指针同步前进,相交点就是环起点
while (slow != fast) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast, *slow;
fast = slow = head;
while (fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) break;
}
// 上面的代码类似 hasCycle 函数
if (fast == nullptr || fast->next == nullptr) {
// fast 遇到空指针说明没有环
return nullptr;
}
// 重新指向头结点
slow = head;
// 快慢指针同步前进,相交点就是环起点
while (slow != fast) {
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
class Solution:
def detectCycle(self, head: ListNode):
fast, slow = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
# 上面的代码类似 hasCycle 函数
if not fast or not fast.next:
# fast 遇到空指针说明没有环
return None
# 重新指向头结点
slow = head
# 快慢指针同步前进,相交点就是环起点
while slow != fast:
fast = fast.next
slow = slow.next
return slow
func detectCycle(head *ListNode) *ListNode {
fast, slow := head, head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
if fast == slow {
break
}
}
// 上面的代码类似 hasCycle 函数
if fast == nil || fast.Next == nil {
// fast 遇到空指针说明没有环
return nil
}
// 重新指向头结点
slow = head
// 快慢指针同步前进,相交点就是环起点
for slow != fast {
fast = fast.Next
slow = slow.Next
}
return slow
}
var detectCycle = function(head) {
let fast, slow;
fast = slow = head;
while (fast !== null && fast.next !== null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) break;
}
// 上面的代码类似 hasCycle 函数
if (fast === null || fast.next === null) {
// fast 遇到空指针说明没有环
return null;
}
// 重新指向头结点
slow = head;
// 快慢指针同步前进,相交点就是环起点
while (slow !== fast) {
fast = fast.next;
slow = slow.next;
}
return slow;
};
本站配套刷题插件
为了尽可能满足不同读者的需求,我开发维护了本站配套刷题插件,以让读者在喜欢的代码编辑器中刷题,方便摸鱼。
在刷题插件中,所有本站讲解过的习题都有特殊加强,可以查看简短思路或详细题解,且支持可视化面板、图片注释等所有本站实用功能。
刷题插件并不是必须安装的,但我会建议安装 Chrome 浏览器插件,因为你在阅读本站时,可能会经常跳转到 LeetCode/力扣 页面上刷题,Chrome 插件能够给你提供一些帮助。vscode/Jetbrain 插件可以根据自己的刷题需求选择安装。
各个刷题插件的安装使用方法详见 Chrome 插件、vscode 插件、Jetbrain 插件。