10个数据 结构:
数组 、 链表 、 栈 、 队列 、 散列表 、 二叉树 、 堆 、 跳
表 、 图 、Trie 树;
10 个算法:
递归 、 排序 、 二分查找 、 搜索 、 哈希算法 、 贪心
算法 、 分治算法 、 回溯算法 、 动态规划 、 字符串匹配算法
每个开发人员都应该知道的10种关键数据结构
需要看的算法书:
算法导论(第四版)自学笔记 目录
算法导论
算法导论pdf
算法图解
啊哈!算法
漫画算法:小灰的算法之旅
算法
算法导论
https://leetcode-cn.com/
algorithm visualizer
代码测试平台:POJ502 北京大学
代码随想录
lucifer
LABULADONG算法网站
不同语言接口的不同实现
不同语言接口的不同实现
有了这个可视化插件,刷题调试更轻松,目前支持 Python3,CPP,JavaScript
刷题插件
强烈推荐大家使用谷歌商店安装, 这样如果有更新可以自动安装,毕竟咱们的插件更新还是蛮快的。
如果实现无法访问谷歌商店,可以使用离线安装,离线包地址
如果离线的无法下载或不知道怎么使用,请看下点进去的主页 README
当然还有别家的刷掉插件
算法时间复杂度
算法通关之路-参考链接.docx
目录:
第1章 预备知识 1
1.1 学习算法需要数学知识吗 1
1.2 基础数据结构和算法 2
1.3 复杂度分析 3
总结 12
第2章 数学之美 14
2.1 两数之和 14
2.2 三数之和 18
2.3 四数之和 19
2.4 四数相加II 22
2.5 最接近的三数之和 24
2.6 最大子序列和 26
2.7 最大数 31
2.8 分数到小数 33
2.9 最大整除子集 35
2.10 质数排列 37
总结 39
第3章 回文的艺术 41
3.1 验证回文字符串Ⅱ 41
3.2 回文链表 44
3.3 回文数 47
3.4 最长回文子串 48
3.5 最长回文子序列 50
3.6 超级回文数 53
总结 56
第4章 游戏之乐 58
4.1 外观数列(报数) 58
4.2 24点 61
4.3 数独游戏 67
4.4 生命游戏 75
总结 78
第5章 深度优先遍历和广度优先遍历 79
5.1 深度优先遍历 79
5.2 广度优先遍历 81
5.3 路径和系列问题 82
5.4 岛屿问题 91
总结 100
第6章 二分法 102
6.1 二分查找 102
6.2 寻找旋转排序数组中的最小值 105
6.3 爱吃香蕉的珂珂 107
6.4 x的平方根 109
6.5 寻找峰值 112
6.6 分割数组的最大值 114
总结 118
第7章 位运算 119
7.1 位1的个数 120
7.2 实现加法 122
7.3 整数替换 124
7.4 只出现一次的数字 127
总结 133
第8章 设计 135
8.1 最小栈 135
8.2 实现 Trie(前缀树) 142
8.3 LRU 缓存机制 146
8.4 LFU 缓存 149
8.5 设计跳表 155
总结 163
第9章 双指针 164
9.1 头/尾指针 166
9.2 快慢指针 171
总结 182
第10章 动态规划 183
10.1 爬楼梯 186
10.2 打家劫舍系列 188
10.3 不同路径 195
10.4 零钱兑换 199
总结 204
第11章 滑动窗口 205
11.1 滑动窗口最大值 206
11.2 最小覆盖子串 209
11.3 替换后的最长重复字符 213
11.4 字符串的排列 216
总结 219
第12章 博弈问题 220
12.1 石子游戏 220
12.2 预测赢家 225
12.3 Nim 游戏 230
12.4 猜数字大小II 233
总结 236
第13章 股票问题 237
13.1 买卖股票的最佳时机 237
13.2 买卖股票的最佳时机II 240
13.3 买卖股票的最佳时机(含手续费) 242
13.4 买卖股票的最佳时机(含冷冻期) 247
13.5 买卖股票的最佳时机IV 249
总结 253
第14章 分治法 254
14.1 合并k个排序链表 255
14.2 数组中的第k个最大元素 260
14.3 搜索二维矩阵 II 265
总结 274
第15章 贪心法 276
15.1 分发饼干 276
15.2 跳跃游戏 278
15.3 任务调度器 282
15.4 分发糖果 284
15.5 无重叠区间 287
总结 289
第16章 回溯法 290
16.1 组合总和 I 290
16.2 组合总和 II 296
16.3 子集 299
16.4 全排列 300
16.5 解数独 301
总结 304
第17章 一些有趣的题目 306
17.1 求众数 II 306
17.2 柱状图中最大的矩形 309
17.3 一周中的第几天 314
17.4 水壶问题 317
17.5 可怜的小猪 321
总结 325
第18章 一些通用解题模板 326
18.1 二分法 326
18.2 回溯法 329
18.3 并查集 330
18.4 BFS 333
18.5 滑动窗口 334
18.6 数学 336
总结 339
第19章 融会贯通 340
19.1 循环移位问题 340
19.2 编辑距离 349
19.3 第k问题 357
总结 369
第20章 解题技巧和面试技巧 370
20.1 看限制条件 371
20.2 预处理 380
20.3 不要忽视暴力法 388
20.4 降维与状态压缩 395
20.5 猜测tag 402
总结 403
官方网址
http://leetcode-solution.cn/book
文前
[1]https://chrome.google.com/webstore/detail/leetcodecheatsheet/fniccleejlofifaakbgppmbbcdfjonl
正文
[1] https://github.com/azl397985856/leetcode/blob/master/daily/2019-07-31.md
[2] https://leetcode-cn.com/problems/add-without-plus-lcci/
[3] https://leetcode-cn.com/problems/divide-two-integers/
[4] https://leetcode-cn.com/problems/multiply-strings/
[5] https://leetcode-cn.com/problems/sqrtx/
[6] https://leetcode-cn.com/problems/powx-n/
[7] https://leetcode-cn.com/problems/count-primes/
[8] https://leetcode-cn.com/problems/reverse-linked-list/description/
[9] https://en.wikipedia.org/wiki/Longest_palindromic_substring
[10]https://zh.wikipedia.org/wiki/Rabin%E2%80%93Karp%E7%AE%97%E6%B3%95
[11]http://dhruvbird.com/lfu.pdf
[12] https://zh.wikipedia.org/wiki/%E5%B0%BE%E8%B0%83%E7%94%A8
[13]https://leetcode.com/articles/unique-paths/
[14] https://leetcode.com/articles/unique-paths/
[15]https://zh.wikipedia.org/wiki/%E9%9B%B6%E5%92%8C%E5%8D%9A%E5%BC%88
[16] https://leetcode-cn.com/problems/merge-two-sorted-lists/
[17]https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm
[18]https://leetcode.com/problems/majority-element-ii/discuss/63500/JAVA-Easy-Version-To-Understand!!!!!!!!!!!!/64925
[19] https://zh.wikipedia.org/wiki/%E8%94%A1%E5%8B%92%E5%85%AC%E5%BC%8F
[20] https://zh.wikipedia.org/wiki/%E8%B2%9D%E7%A5%96%E7%AD%89%E5%BC%8F
[21]https://zh.wikipedia.org/wiki/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95
[22]https://zh.wikisource.org/wiki/%E4%B9%9D%E7%AB%A0%E7%AE%97%E8%A1%93#-.7BA.7Czh-hans:.E5.8D.B7.3Bzh-hant:.E5.8D.B7.7D-.E7.AC.AC.E4.B8.80.E3.80.80.E6.96.B9.E7.94.B0.E4.BB.A5.E5.BE.A1.E7.94.B0.E7.96.87.E7.95.8C.E5.9F.9F
[23]https://zh.wikipedia.org/wiki/%E4%BF%A1%E6%BA%90%E7%BC%96%E7%A0%81%E5%AE%9A%E7%90%86
[24] http://leetcode-solution.cn/
labuladong的算法小抄
力扣官网题号及名称 /V
本书约定 / 1
语言基础 / 5
第1章 核心套路篇 / 21
1.1 学习算法和刷题的框架思维 / 21
1.1.1 数据结构的存储方式 / 21
1.1.2 数据结构的基本操作 / 23
1.1.3 算法刷题指南 / 25
1.1.4 最后总结 / 30
1.2 动态规划解题套路框架 / 31
1.2.1 斐波那契数列 / 32
1.2.2 凑零钱问题 / 37
1.2.3 最后总结 / 42
1.3 回溯算法解题套路框架 / 43
1.3.1 全排列问题 / 43
1.3.2 N 皇后问题 / 48
1.3.3 最后总结 / 51
1.4 BFS 算法套路框架 / 53
1.4.1 算法框架 / 53
1.4.2 二叉树的最小高度 / 54
1.4.3 解开密码锁的最少次数 / 56
1.5 双指针技巧套路框架 / 64
1.5.1 快、慢指针的常用算法 / 64
1.5.2 左、右指针的常用算法 / 68
1.6 我写了首诗,保你闭着眼睛都能写出二分搜索算法 / 71
1.6.1 二分搜索框架 / 72
1.6.2 寻找一个数(基本的二分搜索) / 73
1.6.3 寻找左侧边界的二分搜索 / 75
1.6.4 寻找右侧边界的二分搜索 / 79
1.6.5 逻辑统一 / 82
1.7 我写了一个模板,把滑动窗口算法变成了默写题 / 85
1.7.1 最小覆盖子串 / 87
1.7.2 字符串排列 / 91
1.7.3 找所有字母异位词 / 93
1.7.4 最长无重复子串 / 94
第2章 动态规划系列 / 96
2.1 动态规划设计:最长递增子序列 / 96
2.1.1 动态规划解法 / 97
2.1.2 二分搜索解法 / 100
2.2 二维递增子序列:信封嵌套问题 / 104
2.2.1 题目概述 / 104
2.2.2 思路分析 / 105
2.2.3 最后总结 / 107
2.3 最大子数组问题 / 108
2.3.1 思路分析 / 108
2.3.2 最后总结 / 110
2.4 动态规划答疑:最优子结构及dp 遍历方向 / 111
2.4.1 最优子结构详解 / 111
2.4.2 dp 数组的遍历方向 / 113
2.5 经典动态规划:最长公共子序列 / 117
2.6 经典动态规划:编辑距离 / 123
2.6.1 思路分析 / 124
2.6.2 代码详解 / 125
2.6.3 动态规划优化 / 129
2.6.4 扩展延伸 / 131
2.7 子序列问题解题模板:最长回文子序列 / 136
2.7.1 两种思路 / 136
2.7.2 最长回文子序列 / 137
2.7.3 代码实现 / 139
2.8 状态压缩:对动态规划进行降维打击 / 141
2.9 以最小插入次数构造回文串 / 148
2.9.1 思路分析 / 148
2.9.2 状态转移方程 / 149
2.9.3 代码实现 / 152
2.10 动态规划之正则表达式 / 155
2.10.1 思路分析 / 155
2.10.2 动态规划解法 / 157
2.11 不同的定义产生不同的解法 / 162
2.11.1 第一种思路 / 162
2.11.2 第二种思路 / 165
2.11.3 最后总结 / 167
2.12 经典动态规划:高楼扔鸡蛋 / 168
2.12.1 解析题目 / 168
2.12.2 思路分析 / 169
2.12.3 疑难解答 / 172
2.13 经典动态规划:高楼扔鸡蛋(进阶) / 173
2.13.1 二分搜索优化 / 173
2.13.2 重新定义状态转移 / 176
2.13.3 还可以再优化 / 180
2.14 经典动态规划:戳气球问题 / 181
2.14.1 回溯思路 / 181
2.14.2 动态规划思路 / 182
2.14.3 写出代码 / 185
2.15 经典动态规划:0-1 背包问题 / 188
2.16 经典动态规划:子集背包问题 / 192
2.16.1 问题分析 / 192
2.16.2 思路分析 / 193
2.16.3 进行状态压缩 / 194
2.17 经典动态规划:完全背包问题 / 196
2.18 题目千百变,套路不会变 / 200
2.18.1 线性排列情况 / 200
2.18.2 环形排列情况 / 203
2.18.3 树形排列情况 / 205
2.19 动态规划和回溯算法,到底是什么关系 / 207
2.19.1 回溯思路 / 207
2.19.2 消除重叠子问题 / 210
2.19.3 动态规划 / 211
第3章 数据结构系列 / 216
3.1 手把手教你写 LRU 缓存淘汰算法 / 216
3.1.1 LRU 算法描述 / 218
3.1.2 LRU 算法设计 / 219
3.1.3 代码实现 / 220
3.2 层层拆解,带你手写LFU 算法 / 227
3.2.1 算法描述 / 227
3.2.2 思路分析 / 228
3.2.3 代码框架 / 230
3.2.4 LFU 核心逻辑 / 232
3.3 二叉搜索树操作集锦 / 235
3.3.1 判断 BST 的合法性 / 236
3.3.2 在 BST 中查找一个数是否存在 / 238
3.3.3 在 BST 中插入一个数 / 239
3.3.4 在 BST 中删除一个数 / 239
3.4 完全二叉树的节点数为什么那么难算 / 243
3.4.1 思路分析 / 244
3.4.2 复杂度分析 / 245
3.5 用各种遍历框架序列化和反序列化二叉树 / 247
3.5.1 题目描述 / 247
3.5.2 前序遍历解法 / 248
3.5.3 后序遍历解法 / 252
3.5.4 中序遍历解法 / 255
3.5.5 层级遍历解法 / 255
3.6 Git 原理之二叉树最近公共祖先 / 260
3.6.1 二叉树的最近公共祖先 / 261
3.6.2 思路分析 / 263
3.7 特殊数据结构:单调栈 / 266
3.7.1 单调栈解题模板 / 266
3.7.2 题目变形 / 268
3.7.3 如何处理循环数组 / 268
3.8 特殊数据结构:单调队列 / 271
3.8.1 搭建解题框架 / 271
3.8.2 实现单调队列数据结构 / 273
3.8.3 算法复杂度分析 / 276
3.9 如何判断回文链表 / 277
3.9.1 判断回文单链表 / 277
3.9.2 优化空间复杂度 / 280
3.9.3 最后总结 / 282
3.10 秀操作之纯递归反转链表 / 283
3.10.1 递归反转整个链表 / 283
3.10.2 反转链表前N 个节点 / 286
3.10.3 反转链表的一部分 / 287
3.10.4 最后总结 / 288
3.11 秀操作之k 个一组反转链表 / 289
3.11.1 分析问题 / 289
3.11.2 代码实现 / 291
3.11.3 最后总结 / 292
第4章 算法思维系列 / 293
4.1 回溯算法解决子集、组合、排列问题 / 293
4.1.1 子集 / 293
4.1.2 组合 / 297
4.1.3 排列 / 299
4.2 回溯算法最佳实践:解数独 / 301
4.2.1 直观感受 / 301
4.2.2 代码实现 / 301
4.3 回溯算法最佳实践:括号生成 / 306
4.4 BFS 算法暴力破解各种智力题 / 310
4.4.1 题目解析 / 311
4.4.2 思路分析 / 311
4.5 2Sum 问题的核心思想 / 315
4.5.1 2Sum I / 315
4.5.2 2Sum II / 316
4.5.3 最后总结 / 318
4.6 一个函数解决 nSum 问题 / 319
4.6.1 2Sum 问题 / 319
4.6.2 3Sum 问题 / 322
4.6.3 4Sum 问题 / 324
4.6.4 100Sum 问题 / 325
4.7 拆解复杂问题:实现计算器 / 328
4.7.1 字符串转整数 / 328
4.7.2 处理加减法 / 329
4.7.3 处理乘除法 / 331
4.7.4 处理括号 / 333
4.7.5 最后总结 / 336
4.8 摊烧饼也得有点递归思维 / 337
4.8.1 思路分析 / 338
4.8.2 代码实现 / 339
4.9 前缀和技巧解决子数组问题 / 341
4.9.1 什么是前缀和 / 341
4.9.2 优化解法 / 343
4.9.3 最后总结 / 344
4.10 扁平化嵌套列表 / 345
4.10.1 题目描述 / 345
4.10.2 解题思路 / 346
4.10.3 进阶思路 / 349
第5章 高频面试系列 / 351
5.1 如何高效寻找素数 / 351
5.2 如何高效进行模幂运算 / 355
5.2.1 如何处理数组指数 / 355
5.2.2 如何处理 mod 运算 / 356
5.2.3 如何高效求幂 / 358
5.3 如何运用二分搜索算法 / 360
5.3.1 问题分析 / 360
5.3.2 扩展延伸 / 362
5.4 如何高效解决接雨水问题 / 364
5.5 如何去除有序数组的重复元素 / 371
5.6 如何寻找最长回文子串 / 373
5.7 如何运用贪心思想玩跳跃游戏 / 376
5.8 如何运用贪心算法做时间管理 / 381
5.9 如何判定括号合法性 / 386
5.10 如何调度考生的座位 / 389
5.11 Union-Find 算法详解 / 396
labuladong算法笔记
目录 · · · · · ·
本书约定 / 1
编程语言基础 / 4
第1章 核心框架篇 / 15
1.1 学习数据结构和算法的框架思维 15
1.1.1 数据结构的存储方式 16
1.1.2 数据结构的基本操作 17
1.1.3 算法刷题指南 18
1.2 计算机算法的本质 24
1.2.1 算法的本质 24
1.2.2 数组/ 单链表系列算法 26
1.2.3 二叉树系列算法 28
1.2.4 最后总结 33
1.3 动态规划解题套路框架 33
1.3.1 斐波那契数列 35
1.3.2 凑零钱问题 40
1.3.3 最后总结 45
1.4 回溯算法解题套路框架 46
1.4.1 全排列问题 47
1.4.2 N皇后问题 52
1.4.3 最后总结 55
1.5 BFS算法解题套路框架 55
1.5.1 算法框架 56
1.5.2 二叉树的最小高度 57
1.5.3 解开密码锁的最少次数 59
1.5.4 双向BFS 优化 62
1.6 手把手带你刷二叉树(纲领) 65
1.6.1 二叉树的重要性 66
1.6.2 深入理解前、中、后序 67
1.6.3 两种解题思路 71
1.6.4 后序位置的特殊之处 75
1.6.5 层序遍历 79
1.7 我写了首诗,保你闭着眼睛都能写出二分搜索算法 81
1.7.1 二分搜索框架 82
1.7.2 寻找一个数(基本的二分搜索) 82
1.7.3 寻找左侧边界的二分搜索 84
1.7.4 寻找右侧边界的二分搜索 88
1.7.5 逻辑统一 90
1.8 我写了一个模板,把滑动窗口算法变成了默写题 93
1.8.1 最小覆盖子串 96
1.8.2 字符串排列 100
1.8.3 找所有字母异位词 102
1.8.4 最长无重复子串 103
第2章 手把手刷数据结构 / 105
2.1 数组、链表 105
2.1.1 单链表的六大解题套路 105
2.1.2 数组双指针的解题套路 116
2.1.3 小而美的算法技巧:前缀和数组 124
2.1.4 小而美的算法技巧:差分数组 128
2.2 数据结构设计 134
2.2.1 算法就像搭乐高:带你手写LRU算法 135
2.2.2 算法就像搭乐高:带你手写LFU算法 144
2.2.3 以O(1) 时间复杂度删除/ 查找数组中的任意元素 151
2.2.4 单调栈结构解决三道算法题 159
2.2.5 单调队列结构解决滑动窗口问题 164
第3章 手把手培养算法思维 / 170
3.1 二叉树 170
3.1.1 手把手带你刷二叉树(思路) 170
3.1.2 手把手带你刷二叉树(构造) 179
3.1.3 手把手带你刷二叉树(序列化) 192
3.1.3 零、前/ 中/ 后序和二叉树的唯一性 193
3.1.4 归并排序详解及运用 206
3.2 二叉搜索树 215
3.2.1 手把手带你刷二叉搜索树(特性应用) 215
3.2.2 手把手带你刷二叉搜索树(增删查改) 220
3.2.3 快速排序详解及运用 227
3.3 图论算法 237
3.3.1 图论算法基础 237
3.3.2 Union-Find算法详解 245
3.3.3 最小生成树之 Kruskal算法 259
3.4 暴力搜索算法 268
3.4.1 回溯算法解决子集、排列、组合问题 268
3.4.2 经典回溯算法:集合划分问题 291
3.4.3 DFS算法搞定岛屿系列题目 305
3.4.4 BFS算法解决智力游戏 317
第4章 手把手刷动态规划 / 323
4.1 动态规划核心原理 323
4.1.1 base case 和备忘录的初始值怎么定 323
4.1.2 最优子结构和dp 数组的遍历方向怎么定 329
4.1.3 算法时空复杂度分析实用指南 338
4.1.4 动态规划的降维打击:空间压缩技巧 351
4.2 子序列类型问题 358
4.2.1 动态规划设计:最长递增子序列 358
4.2.2 详解最大子数组和 367
4.2.3 详解编辑距离问题 372
4.2.4 详解最长公共子序列问题 381
4.2.5 详解正则匹配问题 389
4.2.6 子序列问题解题模板 397
4.3 背包问题 404
4.3.1 0-1 背包问题解题框架 404
4.3.2 背包问题变体之子集分割 407
4.3.3 背包问题之零钱兑换 410
4.4 用动态规划玩游戏 414
4.4.1 最小路径和问题 414
4.4.2 动态规划算法通关《魔塔》 419
4.4.3 高楼扔鸡蛋问题 426
4.4.4 戳气球问题 438
第5章 高频面试系列 / 445
5.1 链表操作的递归思维一览 445
5.1.1 递归反转整个链表 446
5.1.2 反转链表前N 个节点 448
5.1.3 反转链表的一部分 449
5.2 田忌赛马背后的算法决策 450
5.3 一道数组去重的算法题把我整蒙了 454
5.4 带权重的随机选择算法 458
5.4.1 解法思路 459
5.4.2 解法代码 460
5.5 二分搜索题型套路分析 462
5.5.1 原始的二分搜索代码 463
5.5.2 二分搜索问题的泛化 465
5.5.3 运用二分搜索的套路框架 467
5.5.4 例题一:珂珂吃香蕉 468
5.5.5 例题二:运送货物 471
5.5.6 例题三:分割数组 474
5.6 如何高效解决接雨水问题 475
5.6.1 核心思路 476
5.6.2 备忘录优化 478
5.6.3 双指针解法 479
5.6.4 扩展延伸 481
5.7 一个函数解决nSum 问题 483
5.7.1 twoSum 问题 483
5.7.2 3Sum 问题 486
5.7.3 4Sum 问题 488
5.7.4 100Sum 问题 489
5.8 一个方法解决最近公共祖先问题 491
5.8.1 寻找一个元素 492
5.8.2 解决五道题目 49
代码随想录
第1章 准备面试要知己知彼 1
1.1 面试官为什么要考查算法 1
1.2 编程语言 2
1.2.1 学好算法之前更要学好编程语言 2
1.2.2 代码规范 2
1.3 如何写简历 5
1.3.1 简历模板 5
1.3.2 谨慎使用“精通” 5
1.3.3 拿不准的内容绝对不要写在简历上 5
1.3.4 项目经验应该如何写 6
1.3.5 博客的重要性 7
1.4 企业技术面试的流程 7
1.4.1 一面——机试面 7
1.4.2 二面——基础算法面 8
1.4.3 三面——综合技术面 8
1.4.4 四面——技术leader面 8
1.4.5 五面——HR面 9
1.5 本章小结 10
第2章 程序的性能分析 11
2.1 时间复杂度分析 11
2.1.1 什么是时间复杂度 11
2.1.2 如何描述时间复杂度 12
2.1.3 递归算法的时间复杂度分析 14
2.2 程序的运行时间 17
2.2.1 超时是怎么回事 17
2.2.2 从硬件配置看计算机的性能 18
2.2.3 测试计算机的运行速度 18
2.3 编程语言的内存管理 20
2.3.1 C++的内存管理 21
2.3.2 如何计算程序占用多少内存 22
2.3.3 内存对齐 22
2.4 空间复杂度分析 24
2.4.1 什么是空间复杂度 24
2.4.2 递归算法的空间复杂度分析 25
2.4.3 以空间换时间是常见的优化思路 32
2.5 本章小结 33
第3章 数组 34
3.1 数组理论基础 34
3.2 二分查找 36
3.2.1 二分法写法(一) 37
3.2.2 二分法写法(二) 38
3.3 移除元素 39
3.3.1 暴力解法 40
3.3.2 双指针法 41
3.4 长度最小的子数组 42
3.4.1 暴力解法 42
3.4.2 滑动窗口 43
3.5 这个循环转懵了很多人 45
3.5.1 循环不变量 45
3.5.2 代码实现 46
3.6 本章小结 48
第4章 链表 49
4.1 链表理论基础 49
4.1.1 链表的类型 49
4.1.2 链表的存储方式 50
4.1.3 链表的定义 51
4.1.4 链表的操作 52
4.1.5 性能分析 52
4.2 用虚拟头节点会方便得多 53
4.3 链表常见的六个操作 57
4.4 反转链表 60
4.4.1 双指针法 60
4.4.2 递归法 61
4.5 删除倒数第n个节点 62
4.6 环形链表 64
4.6.1 判断链表是否有环 65
4.6.2 寻找环的入口 66
4.7 本章小结 69
第5章 哈希表 70
5.1 哈希表理论基础 70
5.1.1 哈希函数 71
5.1.2 哈希碰撞 71
5.1.3 常见的三种哈希结构 73
5.2 有效的字母异位词 74
5.3 两个数组的交集 76
5.4 两数之和 78
5.5 四数相加 80
5.6 三数之和 81
5.6.1 哈希解法 81
5.6.2 双指针法 82
5.7 四数之和 85
5.8 本章小结 87
第6章 字符串 88
6.1 字符串与数组的区别 88
6.2 反转字符串 89
6.3 反转字符串II 90
6.4 反转字符串里的单词 92
6.5 KMP算法理论基础 96
6.5.1 什么是KMP算法 96
6.5.2 什么是前缀表 96
6.5.3 为什么一定要用前缀表 97
6.5.4 如何计算前缀表 98
6.5.5 时间复杂度分析 100
6.6 使用KMP匹配字符串 101
6.6.1 构造next数组 101
6.6.2 使用next数组做匹配 103
6.6.3 前缀表统一减一的代码实现 104
6.6.4 前缀表(不减一)的代码实现 105
6.7 找到重复的子字符串 107
6.8 本章小结 109
第7章 栈与队列 110
7.1 栈与队列理论基础 110
7.2 用栈组成队列 112
7.3 用队列组成栈 114
7.3.1 使用两个队列实现栈 115
7.3.2 使用一个队列实现栈 117
7.4 匹配括号 118
7.5 逆波兰表达式 120
7.6 滑动窗口最大值 122
7.7 前k个高频元素 126
7.8 接雨水 129
7.8.1 双指针解法 130
7.8.2 动态规划解法 132
7.8.3 单调栈解法 133
7.9 本章小结 137
第8章 二叉树 139
8.1 二叉树理论基础 139
8.1.1 二叉树的种类 139
8.1.2 二叉树的存储方式 141
8.1.3 二叉树的遍历方式 142
8.1.4 二叉树的定义 143
8.2 前、中、后序的递归遍历 144
8.3 前、中、后序的迭代遍历 146
8.3.1 前序遍历 146
8.3.2 中序遍历 147
8.3.3 后序遍历 148
8.4 前、中、后序统一迭代法 149
8.5 二叉树的层序遍历 152
8.6 反转二叉树 155
8.6.1 递归法 156
8.6.2 迭代法 156
8.7 对称二叉树 158
8.7.1 递归法 159
8.7.2 迭代法 162
8.8 二叉树的最大深度 164
8.8.1 递归法 165
8.8.2 迭代法 166
8.9 二叉树的最小深度 167
8.9.1 递归法 168
8.9.2 迭代法 170
8.10 平衡二叉树 170
8.10.1 递归法 173
8.10.2 迭代法 175
8.11 二叉树的所有路径 176
8.11.1 递归法 177
8.11.2 迭代法 182
8.12 路径总和 183
8.12.1 递归法 183
8.12.2 迭代法 186
8.12.3 路径总和II 187
8.13 构造一棵二叉树 189
8.13.1 使用中序与后序遍历序列构造二叉树 189
8.13.2 使用前序与中序遍历序列构造二叉树 195
8.13.3 相关思考 197
8.14 合并两棵二叉树 197
8.14.1 递归 198
8.14.2 迭代法 200
8.15 在二叉搜索树中寻找节点 201
8.15.1 递归法 202
8.15.2 迭代法 203
8.16 验证二叉搜索树 204
8.16.1 递归法 205
8.16.2 迭代法 207
8.17 二叉搜索树的最小绝对差 208
8.17.1 递归法 208
8.17.2 迭代法 209
8.18 二叉搜索树中的众数 210
8.18.1 递归法 211
8.18.2 迭代法 215
8.19 二叉树的最近公共祖先 216
8.19.1 普通二叉树 216
8.19.2 二叉搜索树 221
8.20 在二叉搜索树中插入一个节点 224
8.20.1 递归法 225
8.20.2 迭代法 227
8.21 在二叉搜索树中删除一个节点 228
8.21.1 递归法 228
8.21.2 迭代法 230
8.22 修剪二叉搜索树 231
8.22.1 递归法 232
8.22.2 迭代法 234
8.23 构造一棵平衡二叉搜索树 235
8.23.1 递归法 236
8.23.2 迭代法 238
8.24 本章小结 239
第9章 回溯算法 240
9.1 回溯算法理论基础 240
9.1.1 什么是回溯算法 240
9.1.2 回溯法的性能 240
9.1.3 回溯法可以解决的问题 240
9.1.4 如何理解回溯法 241
9.1.5 回溯法模板 241
9.2 组合问题 243
9.2.1 回溯算法 244
9.2.2 剪枝优化 248
9.3 组合总和(一) 250
9.3.1 回溯算法 251
9.3.2 剪枝优化 254
9.4 电话号码的字母组合 255
9.5 组合总和(二) 260
9.5.1 回溯算法 261
9.5.2 剪枝优化 263
9.6 组合总和(三) 265
9.7 分割回文串 270
9.8 复原IP地址 274
9.9 子集问题(一) 279
9.10 子集问题(二) 281
9.11 递增子序列 284
9.11.1 回溯算法 285
9.11.2 哈希优化 287
9.12 排列问题(一) 288
9.13 排列问题(二) 291
9.13.1 回溯算法 291
9.13.2 拓展 293
9.14 N皇后问题 296
9.15 解数独 301
9.15.1 回溯算法 302
9.15.2 判断棋盘是否合法 304
9.16 本章小结 305
第10章 贪心算法 306
10.1 贪心算法理论基础 306
10.1.1 什么是贪心 306
10.1.2 贪心的套路 306
10.2 分发饼干 307
10.3 摆动序列 309
10.4 最大子序和 312
10.5 买卖股票的最佳时机II 314
10.6 跳跃游戏 316
10.7 跳跃游戏II 318
10.7.1 贪心解法(一) 320
10.7.2 贪心解法(二) 320
10.8 加油站 322
10.8.1 暴力解法 323
10.8.2 贪心解法(一) 324
10.8.3 贪心解法(二) 325
10.9 分发糖果 327
10.10 柠檬水找零 330
10.11 用最少数量的箭射爆气球 332
10.12 合并区间 335
10.13 单调递增的数字 338
10.13.1 暴力解法 338
10.13.2 贪心解法 339
10.14 本章小结 340
第11章 动态规划 341
11.1 动态规划理论基础 341
11.1.1 动态规划题目的解题步骤 341
11.1.2 动态规划应该如何排查问题 342
11.2 斐波那契数 343
11.2.1 动态规划解法 344
11.2.2 递归解法 345
11.3 爬楼梯 346
11.4 使用最低花费爬楼梯 349
11.5 不同路径(一) 353
11.5.1 深度优先搜索 354
11.5.2 动态规划 355
11.5.3 数论方法 356
11.6 不同路径(二) 358
11.7 整数拆分 361
11.7.1 动态规划 362
11.7.2 贪心算法 364
11.8 不同的二叉搜索树 364
11.9 0-1背包理论基础 369
11.9.1 二维dp数组 370
11.9.2 一维dp数组 375
11.10 分割等和子集 379
11.11 目标和 382
11.12 一和零 385
11.13 完全背包理论基础 388
11.14 零钱兑换(一) 392
11.15 拼凑一个正整数 395
11.16 多步爬楼梯 398
11.17 零钱兑换(二) 399
11.18 完全平方数 402
11.19 单词拆分 405
11.19.1 回溯算法 406
11.19.2 背包问题 407
11.20 买卖股票的最佳时机 410
11.20.1 暴力枚举 410
11.20.2 贪心算法 411
11.20.3 动态规划 411
11.21 买卖股票的最佳时机II 414
11.22 买卖股票的最佳时机III 416
11.23 买卖股票的最佳时机IV 420
11.24 最佳买卖股票时机(含冷冻期) 423
11.25 买卖股票的最佳时机(含手续费) 426
11.26 最长递增子序列 428
11.27 最长连续递增序列 430
11.27.1 动态规划 430
11.27.2 贪心算法 432
11.28 最长重复子数组 433
11.29 最长公共子序列 436
11.30 不相交的线 438
11.31 最大子序和 440
11.32 判断子序列 441
11.33 不同的子序列 444
11.34 两个字符串的删除操作 447
11.35 编辑距离 450
11.36 回文子串 453
11.36.1 动态规划 453
11.36.2 双指针法 456
11.37 最长回文子序列 457
11.38 本章小结 460
用cpp 进程刷题
vector是一个能够存放任意类型的动态数组,可以动态改变大小
栈
stack<int> sIn;
sIn = stack<int>();
sIn.push(x);//入栈
sOut.empty() //判断是否为空栈
sIn.pop();返回栈顶的值 ;不改变栈的值,查看栈顶的对象而不移除它
sOut.top();//返回栈顶的值 ;不改变栈的值,查看栈顶的对象而不移除它
二维vector数组初始化方法(以元素类型为int为例)
初始化为1:
vector<vector<int>> vec(row, vector<int> (col,1));
387. 字符串中的第一个唯一字符
为了节省空间且全是同样大小写的字母可以用数组且下标大小为26(26个字母),数组也是一种哈稀表
class Solution {
public:
int firstUniqChar(string s) {
int len = s.size();
int hashmap[26] = {0};
int ret = -1;
if(len == 0 )return -1;
if(len == 1) return 0;
for(int i = 0;i<len;i++) {
hashmap[s[i]-'a']++;
}
for(int k = 0;k<len;k++) {
if (hashmap[s[k]-'a'] == 1){
return k;
}
}
return ret;
}
};
反转:
reverse(result.begin(), result.end());
BFS代码模板:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<vector<int>> result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
// 这⾥⼀定要使⽤固定⼤⼩size,不要使⽤que.size(),因为que.size是不断变化的
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
return result;
}
};
不会的
### 思路
滑动窗口,窗口内的都是没有重复的字符,我们需要尽可能的扩大窗口的大小。由于窗口在不停向右滑动,
所以我们只关心每个字符最后出现的位置,并建立映射。窗口的右边界就是当前遍历到的字符的位置
,为了求出窗口的大小,我们需要一个变量left来指向滑动窗口的左边界,这样,如果当前遍历到的字符从未出现过,
那么直接扩大右边界,如果之前出现过,那么就分两种情况,在或不在滑动窗口内,如果不在滑动窗口内,那么就没事,
当前字符可以加进来,如果在的话,就需要先在滑动窗口内去掉这个已经出现过的字符了,去掉的方法并不需要将左边界left
一位一位向右遍历查找,由于我们的HashMap已经保存了该重复字符最后出现的位置,所以直接移动left指针就可以了。
我们维护一个结果res,每次用出现过的窗口大小来更新结果res,就可以得到最终结果了
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int pleft = 0;
int pright = 0;
int res = INT_MIN;
int size = s.size();
if(s.empty())return 0;
if(size == 1)return 1;
unordered_map<char,int> map;
while(pright < size){
if(map.find(s[pright])!= map.end()) {
cout<<s[pleft]<<"["<<endl;
map.erase(s[pleft]); //找到重复的,减少窗口左边,左边界向右移动且删除,直到窗口内没有存在与当前右窗口最新遍历一样的键值
pleft++;
}else { //没有重复的,扩大窗口右边
cout<<s[pright]<<"]"<<endl;
map[s[pright]] = pright;
pright++;
res = max(res,(int)map.size());
}
}
return res;
}
};
**复杂度分析**
- 时间复杂度:O(n),
- 空间复杂度:O(n)
关于链表是否有环:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == nullptr) return nullptr;
if(head->next == nullptr) return nullptr;
ListNode* slow = head;
ListNode* fast = head;
while(fast->next !=nullptr && fast->next->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
if(slow == fast) {
ListNode* indexh = head;
ListNode* indexf = fast;
while(indexh != indexf) {
indexh = indexh->next;
indexf = indexf->next;
}
return indexh;
}
}
return nullptr;
}
};
同余定理
Delete Sublist to Make Sum Divisible By K
前缀和
有时修改刷题时,发现计算个别例子过了,但很多数字的测试项却没有过,发现是自己添加了打印,让时间延长了,因此提交时需要将打印
class NumArray {
vector <int> presum;
public:
NumArray(vector<int>& nums) {
presum.resize(nums.size()+1);
for (int i = 1;i < presum.size();i++) {
presum[i] = nums[i-1] + presum[i-1];
}
}
int sumRange(int left, int right) {
int pre_sum = 0;
pre_sum = presum[right+1]-presum[left];
return pre_sum;
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(left,right);
*/
差分数组
class DIFF{
public:
vector<int>diff;
DIFF(vector<int>nums) {
if (nums.size() == 0)return;
diff.resize(nums.size());
diff[0] = nums[0];
for (int i = 1;i < nums.size();i++) {
diff[i] = nums[i]-nums[i-1];
}
}
void increment(int i,int y,int val) {
diff[i] += val;
if (y+1<diff.size())diff[y+1] -= val;
}
vector<int> result() {
vector<int>res(diff.size(),0);
res[0] = diff[0];
for (int i = 1;i < diff.size();i++) {
res[i] = res[i-1] + diff[i];
}
return res;
}
};
使用
class Solution {
public:
// vector<int>diff;
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
vector<int>nums(n);
DIFF *df = new DIFF(nums);
for (vector<int> x:bookings) {
int i = x[0]-1;
int j = x[1]-1;
int r = x[2];
df->increment(i,j,r);
}
return df->result();
}
};
二叉堆
[LeetCode刷题笔记] C++ priority_queue常用操作
最大堆(先取到大值) priority_queue<int, vector<int>, less<int>> lessq;
最小堆(先取到小值) priority_queue<int, vector<int>, greater<int>> greatq;
数据部分:自定义结构体:
struct node {
int x, y,len;
node(int x, int y,int len):x(x), y(y),len(len){}
};
struct cmp {
bool operator()(node a, node b){
return a.len > b.len;//原有位置的比较的结果为true,则互换原有的位置
}
};
priority_queue<node, vector<node>, cmp> pq;
使用
while (!pq.empty()) {
int x = pq.top().x,y = pq.top().y,len = pq.top().len;
pq.pop();
}
pair
pair将两个数据(经常为不同数据类型)组合成一组数据。
pair的实现是一个结构体,主要的两个成员变量是first、second
对于基础数据类型,默认是大顶堆
pair的比较规则:先比较第一个元素,第一个相等比较第二个。
priority_queue<pair<int,int>> pq;
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int>umap;
vector<int>result;
for (int n:nums)umap[n]++;
for(auto i = umap.begin();i != umap.end();i++) {
pq.push(pair<int,int>(i->second,i->first));
}
while ((k--> 0)) {
int x = pq.top().first,y = pq.top().second;
pq.pop();
result.push_back(y);
}
return result;
}
哈稀表,去除重复值
vector<int>& nums
unordered_set<int> pset(nums.begin(),nums.end());
C/C++ 实现 a/b 向上取整和向下取整,其中a > 1, b > 1且 a、b均为整数
除法的向上取整和向下取整
并查集
class UF {
private:
vector<int>parent;
int count;//还有没连通的数量,即没连通的数量
public:
UF(int n) {
// this.count = n;
parent.resize(n);
iota(parent.begin(),parent.end(),0);
}
int find(int index) {
if (index == parent[index])return index;
parent[index] = find(parent[index]);
return parent[index];
}
void unite(int index1,int index2) {
parent[find(index2)] = find(index1);
}
bool connected(int index1,int index2) {
return find(index1) == find(index2);
}
};
使用:
UF *uf = new UF(m);
if (uf->connected(x,y)) {
pq.pop();
continue;
}
uf->unite(x,y);