mirror of
https://github.com/labuladong/fucking-algorithm.git
synced 2025-07-05 03:36:39 +08:00
Merge branch 'master' into ChenjieXu-98
This commit is contained in:
29
README.md
29
README.md
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||

|
||||
|
||||
好消息,《labuladong 的算法小抄》纸质书出版啦!关注公众号查看详情👆
|
||||
|
||||
<p align='center'>
|
||||
<img src="https://gitee.com/labuladong/pictures/raw/master/starHistory.png" width = "600" />
|
||||
</p>
|
||||
@ -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 网站,每篇文章开头都有对应的力扣题目链接,可以边看文章边刷题**:
|
||||
**2、建议收藏我的在线网站,每篇文章开头都有对应的力扣题目链接,可以边看文章边刷题**:
|
||||
|
||||
Gitbook 地址:https://labuladong.gitbook.io/algo/
|
||||
Gitbook 地址:https://labuladong.gitbook.io/algo
|
||||
|
||||
3、建议关注我的公众号 **labuladong**,坚持高质量原创,说是最良心最硬核的技术公众号都不为过。本仓库的文章就是从公众号里整理出来的**一部分**内容,公众号后台回复关键词【电子书】可以获得这份小抄的完整版本;回复【加群】可以加入我们的刷题群,和大家一起讨论算法问题,分享内推机会:
|
||||
GitBook 在国内访问速度很慢,且常被攻击,我特意部署了两个镜像站点,大家可根据网络情况自行选择:
|
||||
|
||||
GitHub Pages 地址:https://labuladong.github.io/algo
|
||||
|
||||
Gitee Pages 地址:https://labuladong.gitee.io/algo
|
||||
|
||||
|
||||
**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,感受一下支配算法的乐趣。
|
||||
|
||||
|
BIN
出版推广1.jpeg
Normal file
BIN
出版推广1.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
@ -428,5 +428,43 @@ KMP 算法也就是动态规划那点事,我们的公众号文章目录有一
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<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
|
||||
```
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
上一篇文章 [几道智力题](https://labuladong.gitbook.io/algo) 中讨论到一个有趣的「石头游戏」,通过题目的限制条件,这个游戏是先手必胜的。但是智力题终究是智力题,真正的算法问题肯定不会是投机取巧能搞定的。所以,本文就借石头游戏来讲讲「假设两个人都足够聪明,最后谁会获胜」这一类问题该如何用动态规划算法解决。
|
||||
|
||||
博弈类问题的套路都差不多,下文举例讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
|
||||
博弈类问题的套路都差不多,下文参考 [这个 YouTube 视频](https://www.youtube.com/watch?v=WxpIHvsu1RI) 的思路讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
|
||||
|
||||
我们「石头游戏」改的更具有一般性:
|
||||
|
||||
@ -212,5 +212,119 @@ int stoneGame(int[] piles) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
* python3版本
|
||||
|
||||
由[SCUHZS](https://github.com/brucecat)提供
|
||||
|
||||
这里采取的是三维的做法
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def stoneGame(self, piles: List[int]) -> bool:
|
||||
n = len(piles)
|
||||
|
||||
# 初始化一个n*n的矩阵 dp数组
|
||||
dp = [[None] * n for i in range(0, n)]
|
||||
|
||||
# 在三角区域填充
|
||||
for i in range(n):
|
||||
for j in range(i, n):
|
||||
dp[i][j] = [0, 0]
|
||||
|
||||
# 填入base case
|
||||
for i in range(0, n):
|
||||
dp[i][i][0] = piles[i]
|
||||
dp[i][i][1] = 0
|
||||
|
||||
# 斜着遍历数组
|
||||
for l in range(2, n + 1):
|
||||
for i in range(0, n-l+1):
|
||||
j = l + i - 1
|
||||
|
||||
|
||||
# 先手选择最左边或最右边的分数
|
||||
left = piles[i] + dp[i + 1][j][1]
|
||||
right = piles[j] + dp[i][j - 1][1]
|
||||
|
||||
# 套用状态转移方程
|
||||
if left > right:
|
||||
dp[i][j][0] = left
|
||||
dp[i][j][1] = dp[i + 1][j][0]
|
||||
else:
|
||||
dp[i][j][0] = right
|
||||
dp[i][j][1] = dp[i][j - 1][0]
|
||||
|
||||
res = dp[0][n - 1]
|
||||
|
||||
return res[0] - res[1] > 0
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
压缩成一维数组,以减小空间复杂度,做法如下。
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def stoneGame(self, piles: List[int]) -> bool:
|
||||
dp = piles.copy()
|
||||
|
||||
for i in range(len(piles) - 1, -1, -1): # 从下往上遍历
|
||||
for j in range(i, len(piles)): # 从前往后遍历
|
||||
dp[j] = max(piles[i] - dp[j], piles[j] - dp[j - 1]) # 计算之后覆盖一维数组的对应位置
|
||||
|
||||
return dp[len(piles) - 1] > 0
|
||||
|
||||
|
||||
```
|
||||
|
||||
* 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);
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
@ -197,5 +197,7 @@ def dp(n, a_num, copy):
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -292,6 +292,7 @@ bool dp(string& s, int i, string& p, int j) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
@ -10,8 +10,8 @@
|
||||

|
||||
|
||||
相关推荐:
|
||||
* [动态规划设计:最大子数组](../动态规划系列/最大子数组.md)
|
||||
* [一文学会递归解题](../投稿/一文学会递归解题.md)
|
||||
* [动态规划设计:最大子数组](https://labuladong.gitbook.io/algo)
|
||||
* [一文学会递归解题](https://labuladong.gitbook.io/algo)
|
||||
|
||||
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
**-----------**
|
||||
|
||||
也许有读者看了前文 [动态规划详解](../动态规划系列/动态规划详解进阶.md),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
|
||||
也许有读者看了前文 [动态规划详解](https://labuladong.gitbook.io/algo),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
|
||||
|
||||
不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」来讲一讲设计动态规划的通用技巧:**数学归纳思想**。
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
**我们的定义是这样的:`dp[i]` 表示以 `nums[i]` 这个数结尾的最长递增子序列的长度。**
|
||||
|
||||
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](../动态规划系列/子序列问题模板.md) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。
|
||||
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](https://labuladong.gitbook.io/algo) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。
|
||||
|
||||
根据这个定义,我们就可以推出 base case:`dp[i]` 初始值为 1,因为以 `nums[i]` 结尾的最长递增子序列起码要包含它自己。
|
||||
|
||||
@ -164,7 +164,7 @@ public int lengthOfLIS(int[] nums) {
|
||||
|
||||
我们只要把处理扑克牌的过程编程写出来即可。每次处理一张扑克牌不是要找一个合适的牌堆顶来放吗,牌堆顶的牌不是**有序**吗,这就能用到二分查找了:用二分查找来搜索当前牌应放置的位置。
|
||||
|
||||
PS:旧文[二分查找算法详解](../算法思维系列/二分查找详解.md)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
|
||||
PS:旧文[二分查找算法详解](https://labuladong.gitbook.io/algo)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
|
||||
|
||||
```java
|
||||
public int lengthOfLIS(int[] nums) {
|
||||
@ -212,5 +212,94 @@ public int lengthOfLIS(int[] nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
```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++
|
||||
class Solution {
|
||||
public:
|
||||
int lengthOfLIS(vector<int>& nums) {
|
||||
/* len 为牌的数量 */
|
||||
int len = nums.size();
|
||||
vector<int> top(len, 0);
|
||||
/* 牌堆数初始化为0 */
|
||||
int piles = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
/* nums[i] 为要处理的扑克牌 */
|
||||
int poker = nums[i];
|
||||
|
||||
/***** 搜索左侧边界的二分查找 *****/
|
||||
int left = 0, right = piles;
|
||||
while (left < right) {
|
||||
int mid = left + (right - left) / 2;
|
||||
if (top[mid] > poker) {
|
||||
right = mid;
|
||||
} else if (top[mid] < poker) {
|
||||
left = mid + 1;
|
||||
} else if (top[mid] == poker) {
|
||||
right = mid;
|
||||
}
|
||||
}
|
||||
/*********************************/
|
||||
|
||||
/* 没找到合适的牌堆,新建一堆 */
|
||||
if (left == piles)
|
||||
piles++;
|
||||
/* 把这张牌放到牌堆顶 */
|
||||
top[left] = poker;
|
||||
}
|
||||
/* 牌堆数就是 LIS 长度 */
|
||||
return piles;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -146,6 +146,8 @@ int helper(vector<int>& memo, int n) {
|
||||
|
||||
```cpp
|
||||
int fib(int N) {
|
||||
if (N == 0) return 0;
|
||||
if (N == 1) return 1;
|
||||
vector<int> dp(N + 1, 0);
|
||||
// base case
|
||||
dp[1] = dp[2] = 1;
|
||||
@ -200,7 +202,7 @@ int coinChange(int[] coins, int amount);
|
||||
|
||||
比如说 `k = 3`,面值分别为 1,2,5,总金额 `amount = 11`。那么最少需要 3 枚硬币凑出,即 11 = 5 + 5 + 1。
|
||||
|
||||
你认为计算机应该如何解决这个问题?显然,就是把所有肯能的凑硬币方法都穷举出来,然后找找看最少需要多少枚硬币。
|
||||
你认为计算机应该如何解决这个问题?显然,就是把所有可能的凑硬币方法都穷举出来,然后找找看最少需要多少枚硬币。
|
||||
|
||||
**1、暴力递归**
|
||||
|
||||
@ -363,5 +365,48 @@ PS:为啥 `dp` 数组初始化为 `amount + 1` 呢,因为凑成 `amount` 金
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[DapangLiu](https://github.com/DapangLiu) 提供 509. 斐波那契数 Python3 解法代码:
|
||||
|
||||
递归写法
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def fib(self, N: int) -> int:
|
||||
if N <= 1:
|
||||
return N
|
||||
return self.fib(N-1) + self.fib(N-2)
|
||||
```
|
||||
|
||||
动态规划写法
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def fib(self, N: int) -> int:
|
||||
if N == 0:
|
||||
return 0
|
||||
# init
|
||||
result = [0 for i in range(N+1)]
|
||||
result[1] = 1
|
||||
|
||||
# status transition
|
||||
for j in range(2, N+1):
|
||||
result[j] = result[j-1] + result[j-2]
|
||||
return result[-1]
|
||||
```
|
||||
|
||||
动态规划写法 (状态压缩)
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
# current status only depends on two previous status
|
||||
dp_0, dp_1 = 0, 1
|
||||
for _ in range(n):
|
||||
dp_0, dp_1 = dp_1, dp_0 + dp_1
|
||||
return dp_0
|
||||
```
|
@ -16,7 +16,7 @@
|
||||
|
||||
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
|
||||
|
||||
[买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/)
|
||||
[买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock)
|
||||
|
||||
[买卖股票的最佳时机 II](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
很多读者抱怨 LeetCode 的股票系列问题奇技淫巧太多,如果面试真的遇到这类问题,基本不会想到那些巧妙的办法,怎么办?**所以本文拒绝奇技淫巧,而是稳扎稳打,只用一种通用方法解决所用问题,以不变应万变**。
|
||||
|
||||
这篇文章用状态机的技巧来解决,可以全部提交通过。不要觉得这个名词高大上,文学词汇而已,实际上就是 DP table,看一眼就明白了。
|
||||
这篇文章参考 [英文版高赞题解](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/discuss/108870/Most-consistent-ways-of-dealing-with-the-series-of-stock-problems) 的思路,用状态机的技巧来解决,可以全部提交通过。不要觉得这个名词高大上,文学词汇而已,实际上就是 DP table,看一眼就明白了。
|
||||
|
||||
先随便抽出一道题,看看别人的解法:
|
||||
|
||||
@ -425,5 +425,7 @@ int maxProfit_k_any(int max_k, int[] prices) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,6 +1,6 @@
|
||||
# 动态规划之子序列问题解题模板
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -171,5 +171,7 @@ int longestPalindromeSubseq(string s) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,labuladong 带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,7 +1,5 @@
|
||||
# 团灭 LeetCode 打家劫舍问题
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://www.zhihu.com/people/labuladong"><img src="https://img.shields.io/badge/%E7%9F%A5%E4%B9%8E-@labuladong-000000.svg?style=flat-square&logo=Zhihu"></a>
|
||||
@ -257,5 +255,69 @@ int[] dp(TreeNode root) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
[Shantom](https://github.com/Shantom) 提供 198. House Robber I Python3 解法代码:
|
||||
|
||||
```Python
|
||||
class Solution:
|
||||
def rob(self, nums: List[int]) -> int:
|
||||
# 当前,上一间,上上间
|
||||
cur, pre1, pre2 = 0, 0, 0
|
||||
|
||||
for num in nums:
|
||||
# 当前 = max(上上间+(抢当前),上间(放弃当前))
|
||||
cur = max(pre2 + num, pre1)
|
||||
pre2 = pre1
|
||||
pre1 = cur
|
||||
|
||||
return cur
|
||||
```
|
||||
[Shantom](https://github.com/Shantom) 提供 213. House Robber II Python3 解法代码:
|
||||
|
||||
```Python
|
||||
class Solution:
|
||||
def rob(self, nums: List[int]) -> int:
|
||||
# 只有一间时不成环
|
||||
if len(nums) == 1:
|
||||
return nums[0]
|
||||
|
||||
# 该函数同198题
|
||||
def subRob(nums: List[int]) -> int:
|
||||
# 当前,上一间,上上间
|
||||
cur, pre1, pre2 = 0, 0, 0
|
||||
for num in nums:
|
||||
# 当前 = max(上上间+(抢当前),上间(放弃当前))
|
||||
cur = max(pre2 + num, pre1)
|
||||
pre2 = pre1
|
||||
pre1 = cur
|
||||
return cur
|
||||
|
||||
# 不考虑第一间或者不考虑最后一间
|
||||
return max(subRob(nums[:-1]), subRob(nums[1:]))
|
||||
```
|
||||
[Shantom](https://github.com/Shantom) 提供 337. House Robber III Python3 解法代码:
|
||||
|
||||
```Python
|
||||
class Solution:
|
||||
def rob(self, root: TreeNode) -> int:
|
||||
# 返回值0项为不抢该节点,1项为抢该节点
|
||||
def dp(root):
|
||||
if not root:
|
||||
return 0, 0
|
||||
|
||||
left = dp(root.left)
|
||||
right = dp(root.right)
|
||||
|
||||
# 抢当前,则两个下家不抢
|
||||
do = root.val + left[0] + right[0]
|
||||
# 不抢当前,则下家随意
|
||||
do_not = max(left) + max(right)
|
||||
|
||||
return do_not, do
|
||||
|
||||
return max(dp(root))
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 动态规划答疑篇
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -54,7 +54,7 @@ return result;
|
||||
|
||||
当然,上面这个例子太简单了,不过请读者回顾一下,我们做动态规划问题,是不是一直在求各种最值,本质跟我们举的例子没啥区别,无非需要处理一下重叠子问题。
|
||||
|
||||
前文不[同定义不同解法](../动态规划系列/动态规划之四键键盘.md) 和 [高楼扔鸡蛋进阶](../动态规划系列/高楼扔鸡蛋问题.md) 就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
|
||||
前文不[同定义不同解法](https://labuladong.gitbook.io/algo) 和 [高楼扔鸡蛋进阶](https://labuladong.gitbook.io/algo) 就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
|
||||
|
||||
再举个常见但也十分简单的例子,求一棵二叉树的最大值,不难吧(简单起见,假设节点中的值都是非负数):
|
||||
|
||||
@ -154,5 +154,7 @@ for (int i = 1; i < m; i++)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,4 +1,4 @@
|
||||
# 最长公共子序列
|
||||
# 最长公共子序列
|
||||
|
||||
|
||||
<p align='center'>
|
||||
@ -144,5 +144,67 @@ else:
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
|
||||
[Edwenc](https://github.com/Edwenc) 提供 C++ 代码:
|
||||
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
int longestCommonSubsequence(string text1, string text2) {
|
||||
// 先计算两条字符串的长度
|
||||
int m = text1.size();
|
||||
int n = text2.size();
|
||||
|
||||
// 构建dp矩阵 默认初始值0
|
||||
// 这里会多扩建一边和一列
|
||||
// 因为dp[i][j]的含义是:对于 s1[1..i] 和 s2[1..j],它们的LCS长度是 dp[i][j]。
|
||||
// 所以当i或者j为零时 LCS的长度默认为0
|
||||
vector< vector<int> > dp ( m+1 , vector<int> ( n+1 , 0 ) );
|
||||
|
||||
// 状态转移
|
||||
// i、j都从1开始遍历 因为下面的操作中都会-1 相当于从0开始
|
||||
for ( int i=1 ; i<m+1 ; i++ ){
|
||||
for ( int j=1 ; j<n+1 ; j++ ){
|
||||
// 如果text1和text2相同
|
||||
// 就在它们的前一位基础上加一
|
||||
// 如果不同 只能在之前的两者中去最大
|
||||
dp[i][j] = (text1[i-1] == text2[j-1]) ? dp[i-1][j-1] + 1 : max( dp[i-1][j] , dp[i][j-1] );
|
||||
}
|
||||
}
|
||||
|
||||
// 返回最终右下角的值
|
||||
return dp[m][n];
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
[Shawn](https://github.com/Shawn-Hx) 提供 Java 代码:
|
||||
|
||||
```java
|
||||
public int longestCommonSubsequence(String text1, String text2) {
|
||||
// 字符串转为char数组以加快访问速度
|
||||
char[] str1 = text1.toCharArray();
|
||||
char[] str2 = text2.toCharArray();
|
||||
|
||||
int m = str1.length, n = str2.length;
|
||||
// 构建dp table,初始值默认为0
|
||||
int[][] dp = new int[m + 1][n + 1];
|
||||
// 状态转移
|
||||
for (int i = 1; i <= m; i++)
|
||||
for (int j = 1; j <= n; j++)
|
||||
if (str1[i - 1] == str2[j - 1])
|
||||
// 找到LCS中的字符
|
||||
dp[i][j] = dp[i-1][j-1] + 1;
|
||||
else
|
||||
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
|
||||
|
||||
return dp[m][n];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
@ -288,5 +288,7 @@ class Node {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -155,5 +155,7 @@ int findMinArrowShots(int[][] intvs) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -292,5 +292,7 @@ while (lo < hi) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,6 +1,6 @@
|
||||
# 经典动态规划问题:高楼扔鸡蛋
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -243,7 +243,7 @@ def superEggDrop(self, K: int, N: int) -> int:
|
||||
return dp(K, N)
|
||||
```
|
||||
|
||||
这里就不展开其他解法了,留在下一篇文章 [高楼扔鸡蛋进阶](../动态规划系列/高楼扔鸡蛋进阶.md)
|
||||
这里就不展开其他解法了,留在下一篇文章 [高楼扔鸡蛋进阶](https://labuladong.gitbook.io/algo)
|
||||
|
||||
我觉得吧,我们这种解法就够了:找状态,做选择,足够清晰易懂,可流程化,可举一反三。掌握这套框架学有余力的话,再去考虑那些奇技淫巧也不迟。
|
||||
|
||||
@ -258,5 +258,7 @@ def superEggDrop(self, K: int, N: int) -> int:
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -154,5 +154,7 @@ $ sudo /home/fdl/bin/connect.sh
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -138,5 +138,7 @@ $ cmd1 | cmd2 | cmd3
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -103,5 +103,7 @@ Redis 监听的默认端口是 6379,我们设置它接收网卡 127.0.0.1 的
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -152,5 +152,7 @@ https://github.com/astaxie/build-web-application-with-golang
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -116,5 +116,7 @@ https://sqlzoo.net/
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -199,7 +199,8 @@ HTTPS 协议中的 SSL/TLS 安全层会组合使用以上几种加密方式,**
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
[test ad](https://labuladong.gitbook.io/algo)
|
@ -236,5 +236,7 @@ public Key delMax() {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -307,9 +307,49 @@ void BST(TreeNode root, int target) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
### c++
|
||||
|
||||
[dekunma](https://www.linkedin.com/in/dekun-ma-036a9b198/)提供第98题C++代码:
|
||||
```C++
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
* struct TreeNode {
|
||||
* int val;
|
||||
* TreeNode *left;
|
||||
* TreeNode *right;
|
||||
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
|
||||
* };
|
||||
*/
|
||||
class Solution {
|
||||
public:
|
||||
bool isValidBST(TreeNode* root) {
|
||||
// 用helper method求解
|
||||
return isValidBST(root, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool isValidBST(TreeNode* root, TreeNode* min, TreeNode* max) {
|
||||
// base case, root为nullptr
|
||||
if (!root) return true;
|
||||
|
||||
// 不符合BST的条件
|
||||
if (min && root->val <= min->val) return false;
|
||||
if (max && root->val >= max->val) return false;
|
||||
|
||||
// 向左右子树分别递归求解
|
||||
return isValidBST(root->left, min, root)
|
||||
&& isValidBST(root->right, root, max);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### python
|
||||
|
||||
[ChenjieXu](https://github.com/ChenjieXu)提供第98题Python3代码:
|
||||
|
||||
```python
|
||||
@ -331,4 +371,6 @@ def isValidBST(self, root):
|
||||
return True
|
||||
|
||||
return helper(root)
|
||||
|
||||
```
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||

|
||||
|
||||
相关推荐:
|
||||
* [回溯算法解题套路框架](https://labuladong.gitbook.io/algo)
|
||||
* [回溯算法解题套路框架](https://labuladong.gitbook.io/algo)
|
||||
* [动态规划解题套路框架](https://labuladong.gitbook.io/algo)
|
||||
|
||||
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
[503.下一个更大元素II](https://leetcode-cn.com/problems/next-greater-element-ii)
|
||||
|
||||
[1118.一月有多少天](https://leetcode-cn.com/problems/number-of-days-in-a-month)
|
||||
[739.每日温度](https://leetcode-cn.com/problems/daily-temperatures/)
|
||||
|
||||
**-----------**
|
||||
|
||||
@ -82,7 +82,7 @@ vector<int> nextGreaterElement(vector<int>& nums) {
|
||||
|
||||
### 问题变形
|
||||
|
||||
单调栈的使用技巧差不多了,来一个简单的变形,力扣第 1118 题「一月有多少天」:
|
||||
单调栈的使用技巧差不多了,来一个简单的变形,力扣第 739 题「每日温度」:
|
||||
|
||||
给你一个数组 `T`,这个数组存放的是近几天的天气气温,你返回一个等长的数组,计算:**对于每一天,你还要至少等多少天才能等到一个更暖和的气温;如果等不到那一天,填 0**。
|
||||
|
||||
@ -178,5 +178,29 @@ vector<int> nextGreaterElements(vector<int>& nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
### java
|
||||
|
||||
```java
|
||||
// 739. Daily Temperatures
|
||||
class Solution {
|
||||
public int[] dailyTemperatures(int[] T) {
|
||||
Stack<Integer> stack = new Stack<>();
|
||||
int[] ans = new int[T.length];
|
||||
for (int i = 0; i < T.length; i++) {
|
||||
// 如果压栈之后不满足单调递减,弹出元素,直至保持单调性
|
||||
while (!stack.isEmpty() && T[i] > T[stack.peek()]) {
|
||||
int index = stack.pop();
|
||||
// 被弹出的元素(T[index])都是小于当前的元素(T[i]),由于栈内元素单调递减,大于被弹出元素(index)的最近的就是当前元素(i)
|
||||
ans[index] = i - index;
|
||||
}
|
||||
stack.push(i);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -207,5 +207,54 @@ vector<int> maxSlidingWindow(vector<int>& nums, int k) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
```java
|
||||
class Solution {
|
||||
public int[] maxSlidingWindow(int[] nums, int k) {
|
||||
int len = nums.length;
|
||||
// 判断数组或者窗口长度为0的情况
|
||||
if (len * k == 0) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
/*
|
||||
采用两端扫描的方法
|
||||
将数组分成大小为 k 的若干个窗口, 对每个窗口分别从左往右和从右往左扫描, 记录扫描的最大值
|
||||
left[] 记录从左往右扫描的最大值
|
||||
right[] 记录从右往左扫描的最大值
|
||||
*/
|
||||
int[] left = new int[len];
|
||||
int[] right = new int[len];
|
||||
|
||||
for (int i = 0; i < len; i = i + k) {
|
||||
// 每个窗口中的第一个值
|
||||
left[i] = nums[i];
|
||||
// 窗口的最后边界
|
||||
int index = i + k - 1 >= len ? len - 1 : i + k - 1;
|
||||
// 每个窗口的最后一个值
|
||||
right[index] = nums[index];
|
||||
// 对该窗口从左往右扫描
|
||||
for (int j = i + 1; j <= index; j++) {
|
||||
left[j] = Math.max(left[j - 1], nums[j]);
|
||||
}
|
||||
// 对该窗口从右往左扫描
|
||||
for (int j = index - 1; j >= i; j--) {
|
||||
right[j] = Math.max(right[j + 1], nums[j]);
|
||||
}
|
||||
}
|
||||
|
||||
int[] arr = new int[len - k + 1];
|
||||
|
||||
// 对于第 i 个位置, 它一定是该窗口从右往左扫描数组中的最后一个值, 相对的 i + k - 1 是该窗口从左向右扫描数组中的最后一个位置
|
||||
// 对两者取最大值即可
|
||||
for (int i = 0; i < len - k + 1; i++) {
|
||||
arr[i] = Math.max(right[i], left[i + k - 1]);
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 拆解复杂问题:实现计算器
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -303,5 +303,7 @@ def calculate(s: str) -> int:
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -299,5 +299,124 @@ PS:本文前两张图片和 GIF 是我第一次尝试用平板的绘图软件
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[happy-yuxuan](https://github.com/happy-yuxuan) 提供 C++ 代码:
|
||||
|
||||
```c++
|
||||
static int timestamp = 0;
|
||||
class Tweet {
|
||||
private:
|
||||
int id;
|
||||
int time;
|
||||
public:
|
||||
Tweet *next;
|
||||
// id为推文内容,time为发文时间
|
||||
Tweet(int id, int time) {
|
||||
this->id = id;
|
||||
this->time = time;
|
||||
next = nullptr;
|
||||
}
|
||||
int getId() const {
|
||||
return this->id;
|
||||
}
|
||||
int getTime() const {
|
||||
return this->time;
|
||||
}
|
||||
};
|
||||
class User {
|
||||
private:
|
||||
int id;
|
||||
public:
|
||||
Tweet *head; // 发布的Twitter,用链表表示
|
||||
unordered_set<int> followed; // 用户关注了那些人
|
||||
User(int userId) {
|
||||
this->id = userId;
|
||||
head = nullptr;
|
||||
// 要先把自己关注了
|
||||
followed.insert(id);
|
||||
}
|
||||
void follow(int userId) {
|
||||
followed.insert(userId);
|
||||
}
|
||||
void unfollow(int userId) {
|
||||
// 不可以取关自己
|
||||
if (userId != this->id)
|
||||
followed.erase(userId);
|
||||
}
|
||||
void post(int contentId) {
|
||||
Tweet *twt = new Tweet(contentId, timestamp);
|
||||
timestamp++;
|
||||
// 将新建的推文插入链表头
|
||||
// 越靠前的推文 timestamp 值越大
|
||||
twt->next = head;
|
||||
head = twt;
|
||||
}
|
||||
};
|
||||
class Twitter {
|
||||
private:
|
||||
// 映射将 userId 和 User 对象对应起来
|
||||
unordered_map<int, User*> userMap;
|
||||
// 判断该用户存不存在系统中,即userMap中存不存在id
|
||||
inline bool contain(int id) {
|
||||
return userMap.find(id) != userMap.end();
|
||||
}
|
||||
public:
|
||||
Twitter() {
|
||||
userMap.clear();
|
||||
}
|
||||
/* user 发表一条 tweet 动态 */
|
||||
void postTweet(int userId, int tweetId) {
|
||||
if (!contain(userId))
|
||||
userMap[userId] = new User(userId);
|
||||
userMap[userId]->post(tweetId);
|
||||
}
|
||||
/* 返回该 user 关注的人(包括他自己)最近的动态 id,
|
||||
最多 10 条,而且这些动态必须按从新到旧的时间线顺序排列。*/
|
||||
vector<int> getNewsFeed(int userId) {
|
||||
vector<int> ret;
|
||||
if (!contain(userId)) return ret;
|
||||
// 构造一个自动通过Tweet发布的time属性从大到小排序的二叉堆
|
||||
typedef function<bool(const Tweet*, const Tweet*)> Compare;
|
||||
Compare cmp = [](const Tweet *a, const Tweet *b) {
|
||||
return a->getTime() < b->getTime();
|
||||
};
|
||||
priority_queue<Tweet*, vector<Tweet*>, Compare> q(cmp);
|
||||
// 关注列表的用户Id
|
||||
unordered_set<int> &users = userMap[userId]->followed;
|
||||
// 先将所有链表头节点插入优先级队列
|
||||
for (int id : users) {
|
||||
if (!contain(id)) continue;
|
||||
Tweet *twt = userMap[id]->head;
|
||||
if (twt == nullptr) continue;
|
||||
q.push(twt);
|
||||
}
|
||||
while (!q.empty()) {
|
||||
Tweet *t = q.top(); q.pop();
|
||||
ret.push_back(t->getId());
|
||||
if (ret.size() == 10) return ret; // 最多返回 10 条就够了
|
||||
if (t->next)
|
||||
q.push(t->next);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/* follower 关注 followee */
|
||||
void follow(int followerId, int followeeId) {
|
||||
// 若 follower 不存在,则新建
|
||||
if (!contain(followerId))
|
||||
userMap[followerId] = new User(followerId);
|
||||
// 若 followee 不存在,则新建
|
||||
if (!contain(followeeId))
|
||||
userMap[followeeId] = new User(followeeId);
|
||||
userMap[followerId]->follow(followeeId);
|
||||
}
|
||||
/* follower 取关 followee,如果 Id 不存在则什么都不做 */
|
||||
void unfollow(int followerId, int followeeId) {
|
||||
if (contain(followerId))
|
||||
userMap[followerId]->unfollow(followeeId);
|
||||
}
|
||||
};
|
||||
```
|
@ -215,5 +215,7 @@ ListNode reverseBetween(ListNode head, int m, int n) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -227,5 +227,7 @@ public boolean empty() {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -236,5 +236,7 @@ int fill(int[][] image, int x, int y,
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -247,5 +247,7 @@ boolean equationsPossible(String[] equations) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -314,5 +314,7 @@ Union-Find 算法的复杂度可以这样分析:构造函数初始化数据结
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -182,5 +182,7 @@ int[] twoSum(int[] nums, int target) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -98,5 +98,7 @@
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -65,7 +65,7 @@ int binarySearch(int[] nums, int target) {
|
||||
|
||||
### 一、寻找一个数(基本的二分搜索)
|
||||
|
||||
这个场景是最简单的,肯能也是大家最熟悉的,即搜索一个数,如果存在,返回其索引,否则返回 -1。
|
||||
这个场景是最简单的,可能也是大家最熟悉的,即搜索一个数,如果存在,返回其索引,否则返回 -1。
|
||||
|
||||
```java
|
||||
int binarySearch(int[] nums, int target) {
|
||||
@ -104,7 +104,7 @@ int binarySearch(int[] nums, int target) {
|
||||
|
||||
`while(left <= right)` 的终止条件是 `left == right + 1`,写成区间的形式就是 `[right + 1, right]`,或者带个具体的数字进去 `[3, 2]`,可见**这时候区间为空**,因为没有数字既大于等于 3 又小于等于 2 的吧。所以这时候 while 循环终止是正确的,直接返回 -1 即可。
|
||||
|
||||
`while(left < right)` 的终止条件是 `left == right`,写成区间的形式就是 `[left, right]`,或者带个具体的数字进去 `[2, 2]`,**这时候区间非空**,还有一个数 2,但此时 while 循环终止了。也就是说这区间 `[2, 2]` 被漏掉了,索引 2 没有被搜索,如果这时候直接返回 -1 就是错误的。
|
||||
`while(left < right)` 的终止条件是 `left == right`,写成区间的形式就是 `[right, right]`,或者带个具体的数字进去 `[2, 2]`,**这时候区间非空**,还有一个数 2,但此时 while 循环终止了。也就是说这区间 `[2, 2]` 被漏掉了,索引 2 没有被搜索,如果这时候直接返回 -1 就是错误的。
|
||||
|
||||
当然,如果你非要用 `while(left < right)` 也可以,我们已经知道了出错的原因,就打个补丁好了:
|
||||
|
||||
@ -505,5 +505,7 @@ int right_bound(int[] nums, int target) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -132,5 +132,7 @@ public int lengthOfLIS(int[] nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -138,5 +138,7 @@
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -156,5 +156,7 @@ for (int i = 1; i < count.length; i++)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -130,5 +130,7 @@ def intervalIntersection(A, B):
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -88,5 +88,7 @@ def merge(intervals):
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -20,7 +20,7 @@
|
||||
|
||||
[141.环形链表II](https://leetcode-cn.com/problems/linked-list-cycle-ii)
|
||||
|
||||
[167.两数之和 II - 输入有序数组](https://leetcode-cn.com/problems/two-sum)
|
||||
[167.两数之和 II - 输入有序数组](https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted)
|
||||
|
||||
**-----------**
|
||||
|
||||
@ -80,6 +80,11 @@ ListNode detectCycle(ListNode head) {
|
||||
if (fast == slow) break;
|
||||
}
|
||||
// 上面的代码类似 hasCycle 函数
|
||||
if (fast == null || fast.next == null) {
|
||||
// fast 遇到空指针说明没有环
|
||||
return null;
|
||||
}
|
||||
|
||||
slow = head;
|
||||
while (slow != fast) {
|
||||
fast = fast.next;
|
||||
@ -227,5 +232,28 @@ void reverse(int[] nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[ryandeng32](https://github.com/ryandeng32/) 提供 Python 代码
|
||||
```python
|
||||
class Solution:
|
||||
def hasCycle(self, head: ListNode) -> bool:
|
||||
# 检查链表头是否为None,是的话则不可能为环形
|
||||
if head is None:
|
||||
return False
|
||||
# 快慢指针初始化
|
||||
slow = fast = head
|
||||
# 若链表非环形则快指针终究会遇到None,然后退出循环
|
||||
while fast.next and fast.next.next:
|
||||
# 更新快慢指针
|
||||
slow = slow.next
|
||||
fast = fast.next.next
|
||||
# 快指针追上慢指针则链表为环形
|
||||
if slow == fast:
|
||||
return True
|
||||
# 退出循环,则链表有结束,不可能为环形
|
||||
return False
|
||||
```
|
||||
|
@ -306,5 +306,7 @@ def backtrack(...):
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -98,5 +98,7 @@ string multiply(string num1, string num2) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -306,5 +306,7 @@ N 叉树的遍历框架,找出来了把~你说,树这种结构重不重要
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -169,5 +169,7 @@ http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -208,5 +208,7 @@ for (int feq : count)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,4 +1,31 @@
|
||||
# 滑动窗口技巧
|
||||
# 滑动窗口算法框架
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
<a href="https://www.zhihu.com/people/labuladong"><img src="https://img.shields.io/badge/%E7%9F%A5%E4%B9%8E-@labuladong-000000.svg?style=flat-square&logo=Zhihu"></a>
|
||||
<a href="https://i.loli.net/2020/10/10/MhRTyUKfXZOlQYN.jpg"><img src="https://img.shields.io/badge/公众号-@labuladong-000000.svg?style=flat-square&logo=WeChat"></a>
|
||||
<a href="https://space.bilibili.com/14089380"><img src="https://img.shields.io/badge/B站-@labuladong-000000.svg?style=flat-square&logo=Bilibili"></a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
**最新消息:关注公众号参与活动,有机会成为 [70k star 算法仓库](https://github.com/labuladong/fucking-algorithm) 的贡献者,机不可失时不再来**!
|
||||
|
||||
相关推荐:
|
||||
* [东哥吃葡萄时竟然吃出一道算法题!](https://labuladong.gitbook.io/algo)
|
||||
* [如何寻找缺失的元素](https://labuladong.gitbook.io/algo)
|
||||
|
||||
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
|
||||
|
||||
[76.最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring)
|
||||
|
||||
[567.字符串的排列](https://leetcode-cn.com/problems/permutation-in-string)
|
||||
|
||||
[438.找到字符串中所有字母异位词](https://leetcode-cn.com/problems/find-all-anagrams-in-a-string)
|
||||
|
||||
[3.无重复字符的最长子串](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters)
|
||||
|
||||
**-----------**
|
||||
|
||||
本文详解「滑动窗口」这种高级双指针技巧的算法框架,带你秒杀几道高难度的子字符串匹配问题。
|
||||
|
||||
@ -334,8 +361,14 @@ class Solution:
|
||||
return s[start:start+min_len] if min_len != float("Inf") else ""
|
||||
```
|
||||
|
||||
[上一篇:二分查找解题框架](https://labuladong.gitbook.io/algo)
|
||||
**_____________**
|
||||
|
||||
[下一篇:双指针技巧解题框架](https://labuladong.gitbook.io/algo)
|
||||
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**。
|
||||
|
||||
[目录](https://labuladong.gitbook.io/algo#目录)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -146,5 +146,7 @@ void reverse(int[] arr, int i, int j) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -101,5 +101,7 @@ PS:**如果有的英文题目实在看不懂,有个小技巧**,你在题
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -272,5 +272,7 @@ https://leetcode.com/tag/divide-and-conquer/
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -343,5 +343,37 @@ class LRUCache {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
```python3
|
||||
"""
|
||||
所谓LRU缓存,根本的难点在于记录最久被使用的键值对,这就设计到排序的问题,
|
||||
在python中,天生具备排序功能的字典就是OrderDict。
|
||||
注意到,记录最久未被使用的键值对的充要条件是将每一次put/get的键值对都定义为
|
||||
最近访问,那么最久未被使用的键值对自然就会排到最后。
|
||||
如果你深入python OrderDict的底层实现,就会知道它的本质是个双向链表+字典。
|
||||
它内置支持了
|
||||
1. move_to_end来重排链表顺序,它可以让我们将最近访问的键值对放到最后面
|
||||
2. popitem来弹出键值对,它既可以弹出最近的,也可以弹出最远的,弹出最远的就是我们要的操作。
|
||||
"""
|
||||
from collections import OrderedDict
|
||||
class LRUCache:
|
||||
def __init__(self, capacity: int):
|
||||
self.capacity = capacity # cache的容量
|
||||
self.visited = OrderedDict() # python内置的OrderDict具备排序的功能
|
||||
def get(self, key: int) -> int:
|
||||
if key not in self.visited:
|
||||
return -1
|
||||
self.visited.move_to_end(key) # 最近访问的放到链表最后,维护好顺序
|
||||
return self.visited[key]
|
||||
def put(self, key: int, value: int) -> None:
|
||||
if key not in self.visited and len(self.visited) == self.capacity:
|
||||
# last=False时,按照FIFO顺序弹出键值对
|
||||
# 因为我们将最近访问的放到最后,所以最远访问的就是最前的,也就是最first的,故要用FIFO顺序
|
||||
self.visited.popitem(last=False)
|
||||
self.visited[key]=value
|
||||
self.visited.move_to_end(key) # 最近访问的放到链表最后,维护好顺序
|
||||
|
||||
```
|
||||
|
@ -166,5 +166,48 @@ for (int i = 0; i < n; i++)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[tonytang731](https://https://github.com/tonytang731) 提供 Python3 代码:
|
||||
```python
|
||||
import math
|
||||
|
||||
class Solution:
|
||||
def minEatingSpeed(self, piles, H):
|
||||
# 初始化起点和终点, 最快的速度可以一次拿完最大的一堆
|
||||
start = 1
|
||||
end = max(piles)
|
||||
|
||||
# while loop进行二分查找
|
||||
while start + 1 < end:
|
||||
mid = start + (end - start) // 2
|
||||
|
||||
# 如果中点所需时间大于H, 我们需要加速, 将起点设为中点
|
||||
if self.timeH(piles, mid) > H:
|
||||
start = mid
|
||||
# 如果中点所需时间小于H, 我们需要减速, 将终点设为中点
|
||||
else:
|
||||
end = mid
|
||||
|
||||
# 提交前确认起点是否满足条件,我们要尽量慢拿
|
||||
if self.timeH(piles, start) <= H:
|
||||
return start
|
||||
|
||||
# 若起点不符合, 则中点是答案
|
||||
return end
|
||||
|
||||
|
||||
|
||||
def timeH(self, piles, K):
|
||||
# 初始化时间
|
||||
H = 0
|
||||
|
||||
#求拿每一堆需要多长时间
|
||||
for pile in piles:
|
||||
H += math.ceil(pile / K)
|
||||
|
||||
return H
|
||||
```
|
||||
|
@ -153,5 +153,7 @@ ListNode reverseKGroup(ListNode head, int k) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -146,5 +146,7 @@ int bulbSwitch(int n) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -165,5 +165,70 @@ boolean isSubsequence(String s, String t) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
[dekunma](https://www.linkedin.com/in/dekun-ma-036a9b198/) 提供C++代码
|
||||
**解法一:遍历(也可以用双指针):**
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
bool isSubsequence(string s, string t) {
|
||||
// 遍历s
|
||||
for(int i = 0; i < s.size(); i++) {
|
||||
// 找到s[i]字符在t中的位置
|
||||
size_t pos = t.find(s[i]);
|
||||
|
||||
// 如果s[i]字符不在t中,返回false
|
||||
if(pos == std::string::npos) return false;
|
||||
// 如果s[i]在t中,后面就只看pos以后的字串,防止重复查找
|
||||
else t = t.substr(pos + 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**解法二:二分查找:**
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
bool isSubsequence(string s, string t) {
|
||||
int m = s.size(), n = t.size();
|
||||
// 对 t 进行预处理
|
||||
vector<int> index[256];
|
||||
for (int i = 0; i < n; i++) {
|
||||
char c = t[i];
|
||||
index[c].push_back(i);
|
||||
}
|
||||
// 串 t 上的指针
|
||||
int j = 0;
|
||||
// 借助 index 查找 s[i]
|
||||
for (int i = 0; i < m; i++) {
|
||||
char c = s[i];
|
||||
// 整个 t 压根儿没有字符 c
|
||||
if (index[c].empty()) return false;
|
||||
int pos = left_bound(index[c], j);
|
||||
// 二分搜索区间中没有找到字符 c
|
||||
if (pos == index[c].size()) return false;
|
||||
// 向前移动指针 j
|
||||
j = index[c][pos] + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 查找左侧边界的二分查找
|
||||
int left_bound(vector<int> arr, int tar) {
|
||||
int lo = 0, hi = arr.size();
|
||||
while (lo < hi) {
|
||||
int mid = lo + (hi - lo) / 2;
|
||||
if (tar > arr[mid]) {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
@ -234,5 +234,7 @@ p.next = reverse(q);
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -109,5 +109,54 @@ char leftOf(char c) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
### Python3
|
||||
```python
|
||||
def isValid(self, s: str) -> bool:
|
||||
left = []
|
||||
leftOf = {
|
||||
')':'(',
|
||||
']':'[',
|
||||
'}':'{'
|
||||
}
|
||||
for c in s:
|
||||
if c in '([{':
|
||||
left.append(c)
|
||||
elif left and leftOf[c]==left[-1]: # 右括号 + left不为空 + 和最近左括号能匹配
|
||||
left.pop()
|
||||
else: # 右括号 + (left为空 / 和堆顶括号不匹配)
|
||||
return False
|
||||
|
||||
# left中所有左括号都被匹配则return True 反之False
|
||||
return not left
|
||||
```
|
||||
|
||||
|
||||
```java
|
||||
//基本思想:每次遇到左括号时都将相对应的右括号')',']'或'}'推入堆栈
|
||||
//如果在字符串中出现右括号,则需要检查堆栈是否为空,以及顶部元素是否与该右括号相同。如果不是,则该字符串无效。
|
||||
//最后,我们还需要检查堆栈是否为空
|
||||
public boolean isValid(String s) {
|
||||
Deque<Character> stack = new ArrayDeque<>();
|
||||
for(char c : s.toCharArray()){
|
||||
//是左括号就将相对应的右括号入栈
|
||||
if(c=='(') {
|
||||
stack.offerLast(')');
|
||||
}else if(c=='{'){
|
||||
stack.offerLast('}');
|
||||
}else if(c=='['){
|
||||
stack.offerLast(']');
|
||||
}else if(stack.isEmpty() || stack.pollLast()!=c){//出现右括号,检查堆栈是否为空,以及顶部元素是否与该右括号相同
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return stack.isEmpty();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
@ -108,8 +108,14 @@ def deleteDuplicates(self, head: ListNode) -> ListNode:
|
||||
return head
|
||||
```
|
||||
|
||||
[上一篇:如何高效解决接雨水问题](https://labuladong.gitbook.io/algo)
|
||||
**_____________**
|
||||
|
||||
[下一篇:如何寻找最长回文子串](https://labuladong.gitbook.io/algo)
|
||||
**刷算法,学套路,认准 labuladong,公众号和 [在线电子书](https://labuladong.gitbook.io/algo) 持续更新最新文章**。
|
||||
|
||||
[目录](https://labuladong.gitbook.io/algo#目录)
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -1,6 +1,6 @@
|
||||
# 回溯算法团灭子集、排列、组合问题
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -281,5 +281,7 @@ void backtrack(int[] nums, LinkedList<Integer> track) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -230,5 +230,7 @@ private int distance(int[] intv) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -175,5 +175,44 @@ int countPrimes(int n) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
C++解法:
|
||||
采用的算法是埃拉托斯特尼筛法
|
||||
埃拉托斯特尼筛法的具体内容就是:**要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。**
|
||||
同时考虑到大于2的偶数都不是素数,所以可以进一步优化成:**要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的奇数倍剔除,剩下的奇数就是素数。**
|
||||
此算法其实就是上面的Java解法所采用的。
|
||||
|
||||
这里提供C++的代码:
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
int countPrimes(int n) {
|
||||
int res = 0;
|
||||
bool prime[n+1];
|
||||
for(int i = 0; i < n; ++i)
|
||||
prime[i] = true;
|
||||
|
||||
for(int i = 2; i <= sqrt(n); ++i) //计数过程
|
||||
{ //外循环优化,因为判断一个数是否为质数只需要整除到sqrt(n),反推亦然
|
||||
if(prime[i])
|
||||
{
|
||||
for(int j = i * i; j < n; j += i) //内循环优化,i*i之前的比如i*2,i*3等,在之前的循环中已经验证了
|
||||
{
|
||||
prime[j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 2; i < n; ++i)
|
||||
if (prime[i]) res++; //最后遍历统计一遍,存入res
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -208,5 +208,102 @@ if (l_max < r_max) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[Yifan Zhang](https://github.com/FanFan0919) 提供 java 代码
|
||||
|
||||
**双指针解法**:时间复杂度 O(N),空间复杂度 O(1)
|
||||
|
||||
对cpp版本的解法有非常微小的优化。
|
||||
因为我们每次循环只会选 left 或者 right 处的柱子来计算,因此我们并不需要在每次循环中同时更新`maxLeft`和`maxRight`。
|
||||
我们可以先比较 `maxLeft` 和 `maxRight`,决定这次选择计算的柱子是 `height[left]` 或者 `height[right]` 后再更新对应的 `maxLeft` 或 `maxRight`。
|
||||
当然这并不会在时间上带来什么优化,只是提供一种思路。
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public int trap(int[] height) {
|
||||
if (height == null || height.length == 0) return 0;
|
||||
int left = 0, right = height.length - 1;
|
||||
int maxLeft = height[left], maxRight = height[right];
|
||||
int res = 0;
|
||||
|
||||
while (left < right) {
|
||||
// 比较 maxLeft 和 maxRight,决定这次计算 left 还是 right 处的柱子
|
||||
if (maxLeft < maxRight) {
|
||||
left++;
|
||||
maxLeft = Math.max(maxLeft, height[left]); // update maxLeft
|
||||
res += maxLeft - height[left];
|
||||
} else {
|
||||
right--;
|
||||
maxRight = Math.max(maxRight, height[right]); // update maxRight
|
||||
res += maxRight - height[right];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
附上暴力解法以及备忘录解法的 java 代码
|
||||
|
||||
**暴力解法**:时间复杂度 O(N^2),空间复杂度 O(1)
|
||||
```java
|
||||
class Solution {
|
||||
public int trap(int[] height) {
|
||||
if (height == null || height.length == 0) return 0;
|
||||
int n = height.length;
|
||||
int res = 0;
|
||||
// 跳过最左边和最右边的柱子,从第二个柱子开始
|
||||
for (int i = 1; i < n - 1; i++) {
|
||||
int maxLeft = 0, maxRight = 0;
|
||||
// 找右边最高的柱子
|
||||
for (int j = i; j < n; j++) {
|
||||
maxRight = Math.max(maxRight, height[j]);
|
||||
}
|
||||
// 找左边最高的柱子
|
||||
for (int j = i; j >= 0; j--) {
|
||||
maxLeft = Math.max(maxLeft, height[j]);
|
||||
}
|
||||
// 如果自己就是最高的话,
|
||||
// maxLeft == maxRight == height[i]
|
||||
res += Math.min(maxLeft, maxRight) - height[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**备忘录解法**:时间复杂度 O(N),空间复杂度 O(N)
|
||||
```java
|
||||
class Solution {
|
||||
public int trap(int[] height) {
|
||||
if (height == null || height.length == 0) return 0;
|
||||
int n = height.length;
|
||||
int res = 0;
|
||||
// 数组充当备忘录
|
||||
int[] maxLeft = new int[n];
|
||||
int[] maxRight = new int[n];
|
||||
// 初始化 base case
|
||||
maxLeft[0] = height[0];
|
||||
maxRight[n - 1] = height[n - 1];
|
||||
|
||||
// 从左向右计算 maxLeft
|
||||
for (int i = 1; i < n; i++) {
|
||||
maxLeft[i] = Math.max(maxLeft[i - 1], height[i]);
|
||||
}
|
||||
// 从右向左计算 maxRight
|
||||
for (int i = n - 2; i >= 0; i--) {
|
||||
maxRight[i] = Math.max(maxRight[i + 1], height[i]);
|
||||
}
|
||||
// 计算答案
|
||||
for (int i = 1; i < n; i++) {
|
||||
res += Math.min(maxLeft[i], maxRight[i]) - height[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
```
|
@ -1,6 +1,6 @@
|
||||
# 如何寻找最长回文子串
|
||||
|
||||
**学好算法全靠套路,认准 labuladong 就够了**。
|
||||
|
||||
|
||||
<p align='center'>
|
||||
<a href="https://github.com/labuladong/fucking-algorithm" target="view_window"><img alt="GitHub" src="https://img.shields.io/github/stars/labuladong/fucking-algorithm?label=Stars&style=flat-square&logo=GitHub"></a>
|
||||
@ -128,5 +128,7 @@ string longestPalindrome(string s) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -145,5 +145,7 @@ $$ -->
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
@ -89,6 +89,7 @@ int missingNumber(int[] nums) {
|
||||
for (int x : nums)
|
||||
sum += x;
|
||||
return expect - sum;
|
||||
}
|
||||
```
|
||||
|
||||
你看,这种解法应该是最简单的,但说实话,我自己也没想到这个解法,而且我去问了几个大佬,他们也没想到这个最简单的思路。相反,如果去问一个初中生,他也许很快就能想到。
|
||||
@ -129,5 +130,52 @@ public int missingNumber(int[] nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[happy-yuxuan](https://github.com/happy-yuxuan) 提供 三种方法的 C++ 代码:
|
||||
|
||||
```c++
|
||||
// 方法:异或元素和索引
|
||||
int missingNumber(vector<int>& nums) {
|
||||
int n = nums.size();
|
||||
int res = 0;
|
||||
// 先和新补的索引异或一下
|
||||
res ^= n;
|
||||
// 和其他的元素、索引做异或
|
||||
for (int i = 0; i < n; i++)
|
||||
res ^= i ^ nums[i];
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
```c++
|
||||
// 方法:等差数列求和
|
||||
int missingNumber(vector<int>& nums) {
|
||||
int n = nums.size();
|
||||
// 公式:(首项 + 末项) * 项数 / 2
|
||||
int expect = (0 + n) * (n + 1) / 2;
|
||||
int sum = 0;
|
||||
for (int x : nums)
|
||||
sum += x;
|
||||
return expect - sum;
|
||||
}
|
||||
```
|
||||
|
||||
```c++
|
||||
// 方法:防止整型溢出
|
||||
int missingNumber(vector<int>& nums) {
|
||||
int n = nums.size();
|
||||
int res = 0;
|
||||
// 新补的索引
|
||||
res += n - 0;
|
||||
// 剩下索引和元素的差加起来
|
||||
for (int i = 0; i < n; i++)
|
||||
res += i - nums[i];
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
@ -136,5 +136,33 @@ vector<int> findErrorNums(vector<int>& nums) {
|
||||
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**。
|
||||
|
||||
<p align='center'>
|
||||
<img src="../pictures/table_qr2.jpg" width=500 >
|
||||
<img src="../pictures/qrcode.jpg" width=200 >
|
||||
</p>
|
||||
|
||||
======其他语言代码======
|
||||
|
||||
[zhuli](https://github.com/1097452462 "zhuli")提供的Java代码:
|
||||
```java
|
||||
class Solution {
|
||||
public int[] findErrorNums(int[] nums) {
|
||||
int n = nums.length;
|
||||
int dup = -1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
// 元素是从 1 开始的
|
||||
int index = Math.abs(nums[i]) - 1;
|
||||
// nums[index] 小于 0 则说明重复访问
|
||||
if (nums[index] < 0)
|
||||
dup = Math.abs(nums[i]);
|
||||
else
|
||||
nums[index] *= -1;
|
||||
}
|
||||
int missing = -1;
|
||||
for (int i = 0; i < n; i++)
|
||||
// nums[i] 大于 0 则说明没有访问
|
||||
if (nums[i] > 0)
|
||||
// 将索引转换成元素
|
||||
missing = i + 1;
|
||||
return new int[]{dup, missing};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
Reference in New Issue
Block a user