Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
brucecat committed Mar 20, 2021
2 parents 00fe454 + 1fbb033 commit 0f1097e
Show file tree
Hide file tree
Showing 69 changed files with 2,224 additions and 262 deletions.
29 changes: 21 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ English version repo and Gitbook is on [english branch](https://github.com/labul
# labuladong 的算法小抄

<p align='center'>
<a href="https://labuladong.gitbook.io/algo" target="_blank"><img alt="Website" src="https://img.shields.io/website?label=%E5%9C%A8%E7%BA%BF%E7%94%B5%E5%AD%90%E4%B9%A6&style=flat-square&down_color=blue&down_message=%E7%82%B9%E8%BF%99%E9%87%8C&up_color=blue&up_message=%E7%82%B9%E8%BF%99%E9%87%8C&url=https%3A%2F%2Flabuladong.gitbook.io%2Falgo&logo=Gitea"></a>
<a href="https://labuladong.gitee.io/algo" target="_blank"><img alt="Website" src="https://img.shields.io/website?label=%E5%9C%A8%E7%BA%BF%E7%94%B5%E5%AD%90%E4%B9%A6&style=flat-square&down_color=blue&down_message=%E7%82%B9%E8%BF%99%E9%87%8C&up_color=blue&up_message=%E7%82%B9%E8%BF%99%E9%87%8C&url=https%3A%2F%2Flabuladong.gitee.io%2Falgo&logo=Gitea"></a>
<a href="https://github.com/labuladong/fucking-algorithm" target="_blank"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
</p>

Expand All @@ -14,6 +14,10 @@ English version repo and Gitbook is on [english branch](https://github.com/labul
<a href="https://space.bilibili.com/14089380" target="_blank"><img src="https://img.shields.io/badge/B站-@labuladong-000000.svg?style=flat-square&logo=Bilibili"></a>
</p>

![](pictures/souyisou.png)

好消息,《labuladong 的算法小抄》纸质书出版啦!关注公众号查看详情👆

<p align='center'>
<img src="https://gitee.com/labuladong/pictures/raw/master/starHistory.png" width = "600" />
</p>
Expand All @@ -25,27 +29,36 @@ English version repo and Gitbook is on [english branch](https://github.com/labul

只想要答案的话很容易,题目评论区五花八门的答案,动不动就秀 python 一行代码解决,有那么多人点赞。问题是,你去做算法题,是去学习编程语言的奇技淫巧的,还是学习算法思维的呢?你的快乐,到底源自复制别人的一行代码通过测试,已完成题目 +1,还是源自自己通过逻辑推理和算法框架不看答案写出解法?

网上总有大佬喷我,说我写这玩意太基础了,根本没必要啰嗦。我只能说大家刷算法就是找工作吃饭的,不是打竞赛的,我也是一路摸爬滚打过来的,我们要的是清楚明白有所得,不是故弄玄虚无所指。不想办法做到通俗易懂,难道要上来先把《算法导论》吹上天,然后把人家都心怀敬仰地劝退?
网上总有大佬喷我,说我写的东西太基础,要么说不能借助框架思维来学习算法。我只能说大家刷算法就是找工作吃饭的,不是打竞赛的,我也是一路摸爬滚打过来的,我们要的是清楚明白有所得,不是故弄玄虚无所指。

不想办法做到通俗易懂,难道要上来先把《算法导论》吹上天,然后把人家都心怀敬仰地劝退?

**做啥事情做多了,都能发现套路的,我把各种算法套路框架总结出来,相信可以帮助其他人少走弯路**。我这个纯靠自学的小童鞋,花了一年时间刷题和总结,自己写了一份算法小抄,后面有目录,这里就不废话了。

### 使用方法

1、**先给本仓库点个 star,满足一下我的虚荣心**,文章质量绝对值你一个 star。我还在继续创作,给我一点继续写文的动力,感谢。
**1、先给本仓库点个 star,满足一下我的虚荣心**,文章质量绝对值你一个 star。我还在继续创作,给我一点继续写文的动力,感谢。

**2、建议收藏我的在线网站,每篇文章开头都有对应的力扣题目链接,可以边看文章边刷题**

Gitbook 地址:https://labuladong.gitbook.io/algo

GitBook 在国内访问速度很慢,且常被攻击,我特意部署了两个镜像站点,大家可根据网络情况自行选择:

GitHub Pages 地址:https://labuladong.github.io/algo

2、**建议收藏我的 Gitbook 网站,每篇文章开头都有对应的力扣题目链接,可以边看文章边刷题**
Gitee Pages 地址:https://labuladong.gitee.io/algo

Gitbook 地址:https://labuladong.gitbook.io/algo/

3、建议关注我的公众号 **labuladong**,坚持高质量原创,说是最良心最硬核的技术公众号都不为过。本仓库的文章就是从公众号里整理出来的**一部分**内容,公众号后台回复关键词【电子书】可以获得这份小抄的完整版本;回复【加群】可以加入我们的刷题群,和大家一起讨论算法问题,分享内推机会:
**3、建议关注我的公众号 labuladong,坚持高质量原创,说是最良心最硬核的技术公众号都不为过**。本仓库的文章就是从公众号里整理出来的**一部分**内容,公众号可以查看更多内容;公众号后台回复关键词【加群】可以加入我们的刷题群,和大家一起讨论算法问题,分享内推机会:

<p align='center'>
<img src="https://gitee.com/labuladong/pictures/raw/master/qrcode.jpg" width = "200" />
</p>

4、欢迎关注 [我的知乎](https://www.zhihu.com/people/labuladong)
**4、欢迎关注 [我的知乎](https://www.zhihu.com/people/labuladong)**

我一直在写优质文章,但是后续的文章只发布到公众号/gitbook/知乎,不能开放到 GitHub。因为本仓库太火了,很多人直接拿我的文章去开付费专栏,价格还不便宜,我这免费写给您看,何必掏冤枉钱呢?所以多多关注本作者,多多宣传,谁也不希望劣币驱逐良币不是么?
我一直在写优质文章,但是后续的文章只发布到公众号/网站/知乎,不能开放到 GitHub。因为本仓库太火了,很多人直接拿我的文章去开付费专栏,价格还不便宜,我这免费写给您看,何必掏冤枉钱呢?所以多多关注本作者,多多宣传,谁也不希望劣币驱逐良币不是么?

其他的先不多说了,直接上干货吧,我们一起搞定 LeetCode,感受一下支配算法的乐趣。

Expand Down
Binary file modified pictures/qrcode.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 出版推广1.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 40 additions & 4 deletions 动态规划系列/动态规划之KMP字符匹配算法.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
![](../pictures/souyisou.png)

相关推荐:
* [经典动态规划:最长公共子序列](https://labuladong.gitbook.io/algo)
* [特殊数据结构:单调栈](https://labuladong.gitbook.io/algo)
* [经典动态规划:最长公共子序列](https://labuladong.gitbook.io/algo/)
* [特殊数据结构:单调栈](https://labuladong.gitbook.io/algo/)

读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:

Expand Down Expand Up @@ -423,12 +423,48 @@ KMP 算法也就是动态规划那点事,我们的公众号文章目录有一

**_____________**

**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo/) 持续更新最新文章**

**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**

<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>

======其他语言代码======
======其他语言代码======
[MoguCloud](https://github.com/MoguCloud) 提供 实现 strStr() 的 Python 完整代码:
```py
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
# 边界条件判断
if not needle:
return 0
pat = needle
txt = haystack

M = len(pat)
# dp[状态][字符] = 下个状态
dp = [[0 for _ in range(256)] for _ in pat]
# base case
dp[0][ord(pat[0])] = 1
# 影子状态 X 初始化为 0
X = 0
for j in range(1, M):
for c in range(256):
dp[j][c] = dp[X][c]
dp[j][ord(pat[j])] = j + 1
# 更新影子状态
X = dp[X][ord(pat[j])]

N = len(txt)
# pat 初始状态为 0
j = 0
for i in range(N):
# 计算 pat 的下一个状态
j = dp[j][ord(txt[i])]
# 到达终止态,返回结果
if j == M:
return i - M + 1
# 没到达终止态,匹配失败
return -1
```
51 changes: 46 additions & 5 deletions 动态规划系列/动态规划之博弈问题.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
![](../pictures/souyisou.png)

相关推荐:
* [40张图解:TCP三次握手和四次挥手面试题](https://labuladong.gitbook.io/algo)
* [如何计算完全二叉树的节点数](https://labuladong.gitbook.io/algo)
* [40张图解:TCP三次握手和四次挥手面试题](https://labuladong.gitbook.io/algo/)
* [如何计算完全二叉树的节点数](https://labuladong.gitbook.io/algo/)

读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:

[877.石子游戏](https://leetcode-cn.com/problems/stone-game)

**-----------**

上一篇文章 [几道智力题](https://labuladong.gitbook.io/algo) 中讨论到一个有趣的「石头游戏」,通过题目的限制条件,这个游戏是先手必胜的。但是智力题终究是智力题,真正的算法问题肯定不会是投机取巧能搞定的。所以,本文就借石头游戏来讲讲「假设两个人都足够聪明,最后谁会获胜」这一类问题该如何用动态规划算法解决。
上一篇文章 [几道智力题](https://labuladong.gitbook.io/algo/) 中讨论到一个有趣的「石头游戏」,通过题目的限制条件,这个游戏是先手必胜的。但是智力题终究是智力题,真正的算法问题肯定不会是投机取巧能搞定的。所以,本文就借石头游戏来讲讲「假设两个人都足够聪明,最后谁会获胜」这一类问题该如何用动态规划算法解决。

博弈类问题的套路都差不多,下文参考 [这个 YouTube 视频](https://www.youtube.com/watch?v=WxpIHvsu1RI) 的思路讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。

Expand Down Expand Up @@ -207,7 +207,7 @@ int stoneGame(int[] piles) {

**_____________**

**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo/) 持续更新最新文章**

**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**

Expand All @@ -221,7 +221,7 @@ int stoneGame(int[] piles) {



python3版本
* python3版本

由[SCUHZS](https://github.com/brucecat)提供

Expand Down Expand Up @@ -287,3 +287,44 @@ class Solution:

```

* C++ 版本

由 [TCeason](https://github.com/TCeason) 提供

这里采用 hash map 来解决问题

```cpp
class Solution {
public:
unordered_map<int, int> memo;

int dfs(vector<int> &piles, int index) {
// 从两边向中间获取
// index 值为 1/2 piles.size() 时可以停止算法
if (index == piles.size() / 2)
return 0;

// 减少计算,快速返回已有结果
if (memo.count(index))
return memo[index];

// 防止第一次取最右时越界
int n = piles.size() - 1;

// 先手选择最左边或最右边后的分数
int l = piles[index] + dfs(piles, index + 1);
int r = piles[n - index] + dfs(piles, index + 1);

// 返回先手左或右边的最高分
return memo[index] = max(l, r);
}

bool stoneGame(vector<int>& piles) {
// 最佳发挥时:
// 先手得分 * 2 > 总大小 则先手者胜利
return dfs(piles, 0) * 2 > accumulate(begin(piles), end(piles), 0);
}
};

```

6 changes: 3 additions & 3 deletions 动态规划系列/动态规划之四键键盘.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
![](../pictures/souyisou.png)

相关推荐:
* [如何高效寻找素数](https://labuladong.gitbook.io/algo)
* [动态规划解题套路框架](https://labuladong.gitbook.io/algo)
* [如何高效寻找素数](https://labuladong.gitbook.io/algo/)
* [动态规划解题套路框架](https://labuladong.gitbook.io/algo/)

读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:

Expand Down Expand Up @@ -192,7 +192,7 @@ def dp(n, a_num, copy):

**_____________**

**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo/) 持续更新最新文章**

**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**

Expand Down
6 changes: 3 additions & 3 deletions 动态规划系列/动态规划之正则表达.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
![](../pictures/souyisou.png)

相关推荐:
* [我写了首诗,把滑动窗口算法算法变成了默写题](https://labuladong.gitbook.io/algo)
* [二分查找高效判定子序列](https://labuladong.gitbook.io/algo)
* [我写了首诗,把滑动窗口算法算法变成了默写题](https://labuladong.gitbook.io/algo/)
* [二分查找高效判定子序列](https://labuladong.gitbook.io/algo/)

读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:

Expand Down Expand Up @@ -287,7 +287,7 @@ bool dp(string& s, int i, string& p, int j) {

**_____________**

**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo/) 持续更新最新文章**

**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**

Expand Down
58 changes: 52 additions & 6 deletions 动态规划系列/动态规划设计:最长递增子序列.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
![](../pictures/souyisou.png)

相关推荐:
* [动态规划设计:最大子数组](https://labuladong.gitbook.io/algo)
* [一文学会递归解题](https://labuladong.gitbook.io/algo)
* [动态规划设计:最大子数组](https://labuladong.gitbook.io/algo/)
* [一文学会递归解题](https://labuladong.gitbook.io/algo/)

读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:

[300.最长上升子序列](https://leetcode-cn.com/problems/longest-increasing-subsequence)

**-----------**

也许有读者看了前文 [动态规划详解](https://labuladong.gitbook.io/algo),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
也许有读者看了前文 [动态规划详解](https://labuladong.gitbook.io/algo/),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?

不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」来讲一讲设计动态规划的通用技巧:**数学归纳思想**

Expand All @@ -43,7 +43,7 @@

**我们的定义是这样的:`dp[i]` 表示以 `nums[i]` 这个数结尾的最长递增子序列的长度。**

PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](https://labuladong.gitbook.io/algo) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](https://labuladong.gitbook.io/algo/) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。

根据这个定义,我们就可以推出 base case:`dp[i]` 初始值为 1,因为以 `nums[i]` 结尾的最长递增子序列起码要包含它自己。

Expand Down Expand Up @@ -164,7 +164,7 @@ public int lengthOfLIS(int[] nums) {

我们只要把处理扑克牌的过程编程写出来即可。每次处理一张扑克牌不是要找一个合适的牌堆顶来放吗,牌堆顶的牌不是**有序**吗,这就能用到二分查找了:用二分查找来搜索当前牌应放置的位置。

PS:旧文[二分查找算法详解](https://labuladong.gitbook.io/algo)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
PS:旧文[二分查找算法详解](https://labuladong.gitbook.io/algo/)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。

```java
public int lengthOfLIS(int[] nums) {
Expand Down Expand Up @@ -207,7 +207,7 @@ public int lengthOfLIS(int[] nums) {

**_____________**

**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo/) 持续更新最新文章**

**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**

Expand All @@ -217,6 +217,51 @@ public int lengthOfLIS(int[] nums) {

======其他语言代码======

```python 动态规划
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
n = len(nums)
f = [1] * (n)

for i in range(n):
for j in range(i):
if nums[j] < nums[i]:
f[i] = max(f[i], f[j] + 1)

res = 0
for i in range(n):
res = max(res, f[i])
return res
```

```python 二分查找
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
stack = []

def find_index(num):
l, r = 0, len(stack)
while l < r:
mid = l + r >> 1
if stack[mid] >= num:
r = mid
else:
l = mid + 1

return r


for num in nums:
if not stack or num > stack[-1]:
stack.append(num)
else:
position = find_index(num)
stack[position] = num

return len(stack)
```


[Kian](https://github.com/KianKw/) 提供 C++ 代码

```c++
Expand Down Expand Up @@ -257,3 +302,4 @@ public:
}
};
```

Loading

0 comments on commit 0f1097e

Please sign in to comment.