提交 c7421c95 编写于 作者: Miykael_xxm's avatar Miykael_xxm 🚴

update master

上级 8365f9ca
......@@ -14,12 +14,6 @@ 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 的算法小抄》出版啦!扫码查看详情,12 月 6 日晚上 12:00 之前限时五折,附赠力扣会员优惠券,扫码即可查看详情👇
![图书二维码](https://i.loli.net/2020/12/03/xXKBpqGzI6ol985.jpg)
<p align='center'>
<img src="https://gitee.com/labuladong/pictures/raw/master/starHistory.png" width = "600" />
</p>
......@@ -43,7 +37,7 @@ English version repo and Gitbook is on [english branch](https://github.com/labul
Gitbook 地址:https://labuladong.gitbook.io/algo/
3、建议关注我的公众号 **labuladong**,坚持高质量原创,说是最良心最硬核的技术公众号都不为过。本仓库的文章就是从公众号里整理出来的**一部分**内容,公众号后台回复关键词【电子书】可以获得这份小抄的完整版本;回复【加群】可以加入我们的刷题群,和大家一起讨论算法问题,分享内推机会:
2、建议关注我的公众号 **labuladong**,坚持高质量原创,说是最良心最硬核的技术公众号都不为过。本仓库的文章就是从公众号里整理出来的**一部分**内容,公众号后台回复关键词【电子书】可以获得这份小抄的完整版本;回复【加群】可以加入我们的刷题群,和大家一起讨论算法问题,分享内推机会:
<p align='center'>
<img src="https://gitee.com/labuladong/pictures/raw/master/qrcode.jpg" width = "200" />
......
[book]
authors = ["labuladong"]
title = "labuladong 的算法小抄"
language = "zh"
multilingual = false
src = "src"
[output.html]
mathjax-support = true
no-section-label = false
git-repository-url = "https://codechina.csdn.net/mirrors/labuladong/fucking-algorithm"
expand = true
\ No newline at end of file
# 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://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>
<p align='center'>
<a href="https://www.github.com/labuladong" target="_blank"><img src="https://img.shields.io/badge/作者-@labuladong-000000.svg?style=flat-square&logo=GitHub"></a>
<a href="https://www.zhihu.com/people/labuladong" target="_blank"><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" target="_blank"><img src="https://img.shields.io/badge/公众号-@labuladong-000000.svg?style=flat-square&logo=WeChat"></a>
<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>
<p align='center'>
<img src="https://gitee.com/labuladong/pictures/raw/master/starHistory.png" width = "600" />
</p>
本仓库总共 60 多篇原创文章,都是基于 LeetCode 的题目,涵盖了所有题型和技巧,而且一定要做到**举一反三,通俗易懂**,绝不是简单的代码堆砌,后面有目录。
我先吐槽几句。**刷题刷题,刷的是题,培养的是思维,本仓库的目的就是传递这种算法思维**。我要是只写一个包含 LeetCode 题目代码的仓库,有个锤子用?没有思路解释,没有思维框架,顶多写个时间复杂度,那玩意一眼就能看出来。
只想要答案的话很容易,题目评论区五花八门的答案,动不动就秀 python 一行代码解决,有那么多人点赞。问题是,你去做算法题,是去学习编程语言的奇技淫巧的,还是学习算法思维的呢?你的快乐,到底源自复制别人的一行代码通过测试,已完成题目 +1,还是源自自己通过逻辑推理和算法框架不看答案写出解法?
网上总有大佬喷我,说我写这玩意太基础了,根本没必要啰嗦。我只能说大家刷算法就是找工作吃饭的,不是打竞赛的,我也是一路摸爬滚打过来的,我们要的是清楚明白有所得,不是故弄玄虚无所指。不想办法做到通俗易懂,难道要上来先把《算法导论》吹上天,然后把人家都心怀敬仰地劝退?
**做啥事情做多了,都能发现套路的,我把各种算法套路框架总结出来,相信可以帮助其他人少走弯路**。我这个纯靠自学的小童鞋,花了一年时间刷题和总结,自己写了一份算法小抄,后面有目录,这里就不废话了。
### 使用方法
1、**先给本仓库点个 star,满足一下我的虚荣心**,文章质量绝对值你一个 star。我还在继续创作,给我一点继续写文的动力,感谢。
2、**建议收藏我的 Gitbook 网站,每篇文章开头都有对应的力扣题目链接,可以边看文章边刷题**
Gitbook 地址:https://labuladong.gitbook.io/algo/
2、建议关注我的公众号 **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)
我一直在写优质文章,但是后续的文章只发布到公众号/gitbook/知乎,不能开放到 GitHub。因为本仓库太火了,很多人直接拿我的文章去开付费专栏,价格还不便宜,我这免费写给您看,何必掏冤枉钱呢?所以多多关注本作者,多多宣传,谁也不希望劣币驱逐良币不是么?
其他的先不多说了,直接上干货吧,我们一起搞定 LeetCode,感受一下支配算法的乐趣。
# 目录
* 第零章、必读系列
* [学习算法和刷题的框架思维](算法思维系列/学习数据结构和算法的高效方法.md)
* [学习数据结构和算法读什么书](算法思维系列/为什么推荐算法4.md)
* [动态规划解题框架](动态规划系列/动态规划详解进阶.md)
* [动态规划答疑篇](动态规划系列/最优子结构.md)
* [回溯算法解题框架](算法思维系列/回溯算法详解修订版.md)
* [为了学会二分查找,我写了首诗](算法思维系列/二分查找详解.md)
* [滑动窗口解题框架](算法思维系列/滑动窗口技巧.md)
* [双指针技巧解题框架](算法思维系列/双指针技巧.md)
* [Linux的进程、线程、文件描述符是什么](技术/linux进程.md)
* [Git/SQL/正则表达式的在线练习平台](技术/在线练习平台.md)
* 第一章、动态规划系列
* [动态规划详解](动态规划系列/动态规划详解进阶.md)
* [动态规划答疑篇](动态规划系列/最优子结构.md)
* [动态规划设计:最长递增子序列](动态规划系列/动态规划设计:最长递增子序列.md)
* [编辑距离](动态规划系列/编辑距离.md)
* [经典动态规划问题:高楼扔鸡蛋](动态规划系列/高楼扔鸡蛋问题.md)
* [经典动态规划问题:高楼扔鸡蛋(进阶)](动态规划系列/高楼扔鸡蛋进阶.md)
* [动态规划之子序列问题解题模板](动态规划系列/子序列问题模板.md)
* [动态规划之博弈问题](动态规划系列/动态规划之博弈问题.md)
* [贪心算法之区间调度问题](动态规划系列/贪心算法之区间调度问题.md)
* [动态规划之KMP字符匹配算法](动态规划系列/动态规划之KMP字符匹配算法.md)
* [团灭 LeetCode 股票买卖问题](动态规划系列/团灭股票问题.md)
* [团灭 LeetCode 打家劫舍问题](动态规划系列/抢房子.md)
* [动态规划之四键键盘](动态规划系列/动态规划之四键键盘.md)
* [动态规划之正则表达](动态规划系列/动态规划之正则表达.md)
* [最长公共子序列](动态规划系列/最长公共子序列.md)
* 第二章、数据结构系列
* [学习算法和刷题的思路指南](算法思维系列/学习数据结构和算法的高效方法.md)
* [学习数据结构和算法读什么书](算法思维系列/为什么推荐算法4.md)
* [二叉堆详解实现优先级队列](数据结构系列/二叉堆详解实现优先级队列.md)
* [LRU算法详解](高频面试系列/LRU算法.md)
* [二叉搜索树操作集锦](数据结构系列/二叉搜索树操作集锦.md)
* [特殊数据结构:单调栈](数据结构系列/单调栈.md)
* [特殊数据结构:单调队列](数据结构系列/单调队列.md)
* [设计Twitter](数据结构系列/设计Twitter.md)
* [递归反转链表的一部分](数据结构系列/递归反转链表的一部分.md)
* [队列实现栈\|栈实现队列](数据结构系列/队列实现栈栈实现队列.md)
* 第三章、算法思维系列
* [算法学习之路](算法思维系列/算法学习之路.md)
* [回溯算法详解](算法思维系列/回溯算法详解修订版.md)
* [回溯算法团灭排列、组合、子集问题](高频面试系列/子集排列组合.md)
* [二分查找详解](算法思维系列/二分查找详解.md)
* [双指针技巧总结](算法思维系列/双指针技巧.md)
* [滑动窗口技巧](算法思维系列/滑动窗口技巧.md)
* [twoSum问题的核心思想](算法思维系列/twoSum问题的核心思想.md)
* [常用的位操作](算法思维系列/常用的位操作.md)
* [拆解复杂问题:实现计算器](数据结构系列/实现计算器.md)
* [烧饼排序](算法思维系列/烧饼排序.md)
* [前缀和技巧](算法思维系列/前缀和技巧.md)
* [字符串乘法](算法思维系列/字符串乘法.md)
* [FloodFill算法详解及应用](算法思维系列/FloodFill算法详解及应用.md)
* [区间调度之区间合并问题](算法思维系列/区间调度问题之区间合并.md)
* [区间调度之区间交集问题](算法思维系列/区间交集问题.md)
* [信封嵌套问题](算法思维系列/信封嵌套问题.md)
* [几个反直觉的概率问题](算法思维系列/几个反直觉的概率问题.md)
* [洗牌算法](算法思维系列/洗牌算法.md)
* [递归详解](算法思维系列/递归详解.md)
* 第四章、高频面试系列
* [如何实现LRU算法](高频面试系列/LRU算法.md)
* [如何高效寻找素数](高频面试系列/打印素数.md)
* [如何计算编辑距离](动态规划系列/编辑距离.md)
* [如何运用二分查找算法](高频面试系列/koko偷香蕉.md)
* [如何高效解决接雨水问题](高频面试系列/接雨水.md)
* [如何去除有序数组的重复元素](高频面试系列/如何去除有序数组的重复元素.md)
* [如何寻找最长回文子串](高频面试系列/最长回文子串.md)
* [如何k个一组反转链表](高频面试系列/k个一组反转链表.md)
* [如何判定括号合法性](高频面试系列/合法括号判定.md)
* [如何寻找消失的元素](高频面试系列/消失的元素.md)
* [如何寻找缺失和重复的元素](高频面试系列/缺失和重复的元素.md)
* [如何判断回文链表](高频面试系列/判断回文链表.md)
* [如何在无限序列中随机抽取元素](高频面试系列/水塘抽样.md)
* [如何调度考生的座位](高频面试系列/座位调度.md)
* [Union-Find算法详解](算法思维系列/UnionFind算法详解.md)
* [Union-Find算法应用](算法思维系列/UnionFind算法应用.md)
* [一行代码就能解决的算法题](高频面试系列/一行代码解决的智力题.md)
* [二分查找高效判定子序列](高频面试系列/二分查找判定子序列.md)
* 第五章、计算机技术
* [Linux的进程、线程、文件描述符是什么](技术/linux进程.md)
* [一文看懂 session 和 cookie](技术/session和cookie.md)
* [关于 Linux shell 你必须知道的](技术/linuxshell.md)
* [加密算法的前身今世](技术/密码技术.md)
* [Git/SQL/正则表达式的在线练习平台](技术/在线练习平台.md)
# 感谢如下大佬参与翻译
按照昵称字典序排名:
[ABCpril](https://github.com/ABCpril),
[andavid](https://github.com/andavid),
[bryceustc](https://github.com/bryceustc),
[build2645](https://github.com/build2645),
[CarrieOn](https://github.com/CarrieOn),
[cooker](https://github.com/xiaochuhub),
[Dong Wang](https://github.com/Coder2Programmer),
[ExcaliburEX](https://github.com/ExcaliburEX),
[floatLig](https://github.com/floatLig),
[ForeverSolar](https://github.com/foreversolar),
[Fulin Li](https://fulinli.github.io/),
[Funnyyanne](https://github.com/Funnyyanne),
[GYHHAHA](https://github.com/GYHHAHA),
[Hi_archer](https://hiarcher.top/),
[Iruze](https://github.com/Iruze),
[Jieyixia](https://github.com/Jieyixia),
[Justin](https://github.com/Justin-YGG),
[Kevin](https://github.com/Kevin-free),
[Lrc123](https://github.com/Lrc123),
[lriy](https://github.com/lriy),
[Lyjeeq](https://github.com/Lyjeeq),
[MasonShu](https://greenwichmt.github.io/),
[Master-cai](https://github.com/Master-cai),
[miaoxiaozui2017](https://github.com/miaoxiaozui2017),
[natsunoyoru97](https://github.com/natsunoyoru97),
[nettee](https://github.com/nettee),
[PaperJets](https://github.com/PaperJets),
[qy-yang](https://github.com/qy-yang),
[realism0331](https://github.com/realism0331),
[SCUhzs](https://github.com/HuangZiSheng001),
[Seaworth](https://github.com/Seaworth),
[shazi4399](https://github.com/shazi4399),
[ShuozheLi](https://github.com/ShuoZheLi/),
[sinjoywong](https://blog.csdn.net/SinjoyWong),
[sunqiuming526](https://github.com/sunqiuming526),
[Tianhao Zhou](https://github.com/tianhaoz95),
[timmmGZ](https://github.com/timmmGZ),
[tommytim0515](https://github.com/tommytim0515),
[upbin](https://github.com/upbin),
[wadegrc](https://github.com/wadegrc),
[walsvid](https://github.com/walsvid),
[warmingkkk](https://github.com/warmingkkk),
[Wonderxie](https://github.com/Wonderxie),
[wsyzxxxx](https://github.com/wsyzxxxx),
[xiaodp](https://github.com/xiaodp),
[youyun](https://github.com/youyun),
[yx-tan](https://github.com/yx-tan),
[Zero](https://github.com/Mr2er0),
[Ziming](https://github.com/ML-ZimingMeng/LeetCode-Python3)
# Donate
如果本仓库对你有帮助,可以请作者喝杯速溶咖啡
<img src="pictures/pay.jpg" width = "200" align=center />
# SUMMARY
- [labuladong 的算法小抄](README.md)
# [第零章、必读系列]()
---
- [学习算法和刷题的框架思维](think_like_computer/learning_data_structure_and_algorithm.md)
- [学习数据结构和算法读什么书](think_like_computer/why_i_recommend_algs4.md)
- [动态规划解题框架](dynamic_programming/AnalysisOfDynamicProgramming.md)
- [动态规划答疑篇](dynamic_programming/OptimalSubstructure.md)
- [回溯算法解题框架](think_like_computer/DetailsaboutBacktracking.md)
- [为了学会二分查找,我写了首诗](think_like_computer/DetailedBinarySearch.md)
- [滑动窗口解题框架](think_like_computer/SlidingWindowTechnique.md)
- [双指针技巧解题框架](think_like_computer/double_pointer.md)
- [Linux的进程、线程、文件描述符是什么](common_knowledge/linuxProcess.md)
- [Git/SQL/正则表达式的在线练习平台](common_knowledge/OnlinePraticePlatform.md)
# [第一章、动态规划系列]()
---
- [动态规划详解](dynamic_programming/AnalysisOfDynamicProgramming.md)
- [动态规划答疑篇](dynamic_programming/OptimalSubstructure.md)
- [动态规划设计:最长递增子序列](dynamic_programming/LongestIncreasingSubsequence.md)
- [编辑距离](dynamic_programming/EditDistance.md)
- [经典动态规划问题:高楼扔鸡蛋](dynamic_programming/ThrowingEggsinHighBuildings.md)
- [经典动态规划问题:高楼扔鸡蛋(进阶)](dynamic_programming/SuperEggDropAdvanced.md)
- [动态规划之子序列问题解题模板](dynamic_programming/StrategiesForSubsequenceProblem.md)
- [动态规划之博弈问题](dynamic_programming/GameProblemsInDynamicProgramming.md)
- [贪心算法之区间调度问题](dynamic_programming/IntervalScheduling.md)
- [动态规划之KMP字符匹配算法](dynamic_programming/KMPCharacterMatchingAlgorithmInDynamicProgramming.md)
- [团灭 LeetCode 股票买卖问题](dynamic_programming/BestTimeToBuyAndSellStock.md)
- [团灭 LeetCode 打家劫舍问题](dynamic_programming/HouseRobber.md)
- [动态规划之四键键盘](dynamic_programming/FourKeysKeyboard.md)
- [动态规划之正则表达](dynamic_programming/RegularExpression.md)
- [最长公共子序列](dynamic_programming/LongestCommonSubsequence.md)
# [第二章、数据结构系列]()
---
- [学习算法和刷题的思路指南](think_like_computer/learning_data_structure_and_algorithm.md)
- [学习数据结构和算法读什么书](think_like_computer/why_i_recommend_algs4.md)
- [二叉堆详解实现优先级队列](data_structure/binary_heap_implements_priority_queues.md)
- [LRU算法详解](interview/LRU_algorithm.md)
- [二叉搜索树操作集锦](data_structure/The_Manipulation_Collection_of_Binary_Search_Tree.md)
- [特殊数据结构:单调栈](data_structure/MonotonicStack.md)
- [特殊数据结构:单调队列](data_structure/Monotonic_queue.md)
- [设计Twitter](data_structure/design_Twitter.md)
- [递归反转链表的一部分](data_structure/reverse_part_of_a_linked_list_via_recursion.md)
- [队列实现栈\|栈实现队列](data_structure/ImplementQueueUsingStacksImplementStackUsingQueues.md)
# [第三章、算法思维系列]()
---
- [算法学习之路](think_like_computer/ThewaytoAlgorithmlearning.md)
- [回溯算法详解](think_like_computer/DetailsaboutBacktracking.md)
- [回溯算法团灭排列、组合、子集问题](interview/Subset_Permutation_Combination.md)
- [二分查找详解](think_like_computer/DetailedBinarySearch.md)
- [双指针技巧总结](think_like_computer/double_pointer.md)
- [滑动窗口技巧](think_like_computer/SlidingWindowTechnique.md)
- [twoSum问题的核心思想](think_like_computer/The_key_to_resolving_TwoSum_problems.md)
- [常用的位操作](think_like_computer/CommonBitManipulation.md)
- [拆解复杂问题:实现计算器](data_structure/Implementing_the_functions_of_a_calculator.md)
- [烧饼排序](think_like_computer/PancakesSorting.md)
- [前缀和技巧](think_like_computer/prefix_sum.md)
- [字符串乘法](think_like_computer/string_multiplication.md)
- [FloodFill算法详解及应用](think_like_computer/flood_fill.md)
- [区间调度之区间合并问题](think_like_computer/IntervalMerging.md)
- [区间调度之区间交集问题](think_like_computer/IntervalIntersection.md)
- [信封嵌套问题](think_like_computer/RussianDollEnvelopes.md)
- [几个反直觉的概率问题](think_like_computer/several_counter_intuitive_probability_problems.md)
- [洗牌算法](think_like_computer/Shuffle_Algorithm.md)
- [递归详解](think_like_computer/RecursionInDetail.md)
# [第四章、高频面试系列]()
---
- [如何实现LRU算法](interview/LRU_algorithm.md)
- [如何高效寻找素数](interview/Print_PrimeNumbers.md)
- [如何计算编辑距离](dynamic_programming/EditDistance.md)
- [如何运用二分查找算法](interview/UsingBinarySearchAlgorithm.md)
- [如何高效解决接雨水问题](interview/Trapping_Rain_Water.md)
- [如何去除有序数组的重复元素](interview/RemoveDuplicatesfromSortedArray.md)
- [如何寻找最长回文子串](interview/TheLongestPalindromicSubstring.md)
- [如何k个一组反转链表](interview/reverse_nodes_in_k_group.md)
- [如何判定括号合法性](interview/valid_parentheses.md)
- [如何寻找消失的元素](interview/missing_elements.md)
- [如何寻找缺失和重复的元素](interview/Find_Duplicate_and_Missing_Element.md)
- [如何判断回文链表](interview/check_palindromic_linkedlist.md)
- [如何在无限序列中随机抽取元素](interview/ReservoirSampling.md)
- [如何调度考生的座位](interview/Seatscheduling.md)
- [Union-Find算法详解](think_like_computer/Union_find_Explanation.md)
- [Union-Find算法应用](think_like_computer/Union_find_Application.md)
- [一行代码就能解决的算法题](interview/one_line_code_puzzles.md)
- [二分查找高效判定子序列](interview/findSebesquenceWithBinarySearch.md)
# [第五章、计算机技术]()
---
- [Linux的进程、线程、文件描述符是什么](common_knowledge/linuxProcess.md)
- [一文看懂 session 和 cookie](common_knowledge/SessionAndCookie.md)
- [关于 Linux shell 你必须知道的](common_knowledge/linuxshell.md)
- [加密算法的前身今世](common_knowledge/Cryptology.md)
- [Git/SQL/正则表达式的在线练习平台](common_knowledge/OnlinePraticePlatform.md)
\ No newline at end of file
......@@ -199,8 +199,7 @@ HTTPS 协议中的 SSL/TLS 安全层会组合使用以上几种加密方式,**
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
[test ad](https://labuladong.gitbook.io/algo)
\ No newline at end of file
......@@ -116,7 +116,5 @@ https://sqlzoo.net/
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>
======其他语言代码======
\ No newline at end of file
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
\ No newline at end of file
......@@ -152,7 +152,5 @@ https://github.com/astaxie/build-web-application-with-golang
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>
======其他语言代码======
\ No newline at end of file
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
\ No newline at end of file
......@@ -138,7 +138,5 @@ $ cmd1 | cmd2 | cmd3
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -154,7 +154,5 @@ $ sudo /home/fdl/bin/connect.sh
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -103,7 +103,5 @@ Redis 监听的默认端口是 6379,我们设置它接收网卡 127.0.0.1 的
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>
======其他语言代码======
\ No newline at end of file
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
\ No newline at end of file
......@@ -227,7 +227,5 @@ public boolean empty() {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
# 拆解复杂问题:实现计算器
**学好算法全靠套路,认准 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,7 +303,5 @@ def calculate(s: str) -> int:
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -11,7 +11,7 @@
![](../pictures/souyisou.png)
相关推荐:
* [回溯算法解题套路框架](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)
[739.每日温度](https://leetcode-cn.com/problems/daily-temperatures/)
[1118.一月有多少天](https://leetcode-cn.com/problems/number-of-days-in-a-month)
**-----------**
......@@ -82,7 +82,7 @@ vector<int> nextGreaterElement(vector<int>& nums) {
### 问题变形
单调栈的使用技巧差不多了,来一个简单的变形,力扣第 739 题「每日温度」:
单调栈的使用技巧差不多了,来一个简单的变形,力扣第 1118 题「一月有多少天」:
给你一个数组 `T`,这个数组存放的是近几天的天气气温,你返回一个等长的数组,计算:**对于每一天,你还要至少等多少天才能等到一个更暖和的气温;如果等不到那一天,填 0**
......@@ -178,7 +178,5 @@ vector<int> nextGreaterElements(vector<int>& nums) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>
======其他语言代码======
\ No newline at end of file
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
\ No newline at end of file
......@@ -207,7 +207,5 @@ vector<int> maxSlidingWindow(vector<int>& nums, int k) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -307,39 +307,5 @@ void BST(TreeNode root, int target) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
[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);
}
};
```
......@@ -236,7 +236,5 @@ public Key delMax() {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -299,7 +299,5 @@ PS:本文前两张图片和 GIF 是我第一次尝试用平板的绘图软件
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -215,7 +215,5 @@ ListNode reverseBetween(ListNode head, int m, int n) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -146,8 +146,6 @@ 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;
......@@ -202,7 +200,7 @@ int coinChange(int[] coins, int amount);
比如说 `k = 3`,面值分别为 1,2,5,总金额 `amount = 11`。那么最少需要 3 枚硬币凑出,即 11 = 5 + 5 + 1。
你认为计算机应该如何解决这个问题?显然,就是把所有能的凑硬币方法都穷举出来,然后找找看最少需要多少枚硬币。
你认为计算机应该如何解决这个问题?显然,就是把所有能的凑硬币方法都穷举出来,然后找找看最少需要多少枚硬币。
**1、暴力递归**
......@@ -365,48 +363,5 @@ PS:为啥 `dp` 数组初始化为 `amount + 1` 呢,因为凑成 `amount` 金
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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
```
\ No newline at end of file
......@@ -16,7 +16,7 @@
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
[买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock)
[买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/)
[买卖股票的最佳时机 II](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
......@@ -32,7 +32,7 @@
很多读者抱怨 LeetCode 的股票系列问题奇技淫巧太多,如果面试真的遇到这类问题,基本不会想到那些巧妙的办法,怎么办?**所以本文拒绝奇技淫巧,而是稳扎稳打,只用一种通用方法解决所用问题,以不变应万变**
这篇文章参考 [英文版高赞题解](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,看一眼就明白了。
这篇文章用状态机的技巧来解决,可以全部提交通过。不要觉得这个名词高大上,文学词汇而已,实际上就是 DP table,看一眼就明白了。
先随便抽出一道题,看看别人的解法:
......@@ -425,7 +425,5 @@ int maxProfit_k_any(int max_k, int[] prices) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -288,7 +288,5 @@ class Node {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -197,7 +197,5 @@ def dp(n, a_num, copy):
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -22,7 +22,7 @@
上一篇文章 [几道智力题](https://labuladong.gitbook.io/algo) 中讨论到一个有趣的「石头游戏」,通过题目的限制条件,这个游戏是先手必胜的。但是智力题终究是智力题,真正的算法问题肯定不会是投机取巧能搞定的。所以,本文就借石头游戏来讲讲「假设两个人都足够聪明,最后谁会获胜」这一类问题该如何用动态规划算法解决。
博弈类问题的套路都差不多,下文参考 [这个 YouTube 视频](https://www.youtube.com/watch?v=WxpIHvsu1RI) 的思路讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
博弈类问题的套路都差不多,下文举例讲解,其核心思路是在二维 dp 的基础上使用元组分别存储两个人的博弈结果。掌握了这个技巧以后,别人再问你什么俩海盗分宝石,俩人拿硬币的问题,你就告诉别人:我懒得想,直接给你写个算法算一下得了。
我们「石头游戏」改的更具有一般性:
......@@ -212,119 +212,5 @@ int stoneGame(int[] piles) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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);
}
};
```
# 团灭 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>
......@@ -255,69 +257,5 @@ int[] dp(TreeNode root) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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))
```
......@@ -73,14 +73,8 @@ public int intervalSchedule(int[][] intvs) {
if (intvs.length == 0) return 0;
// 按 end 升序排序
Arrays.sort(intvs, new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
// 这里不能使用 a[1] - b[1],要注意溢出问题
if (a[1] < b[1])
return -1;
else if (a[1] > b[1])
return 1;
else return 0;
return a[1] - b[1];
}
});
// 至少有一个区间不相交
......@@ -155,7 +149,5 @@ int findMinArrowShots(int[][] intvs) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -428,7 +428,5 @@ KMP 算法也就是动态规划那点事,我们的公众号文章目录有一
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
# 最长公共子序列
# 最长公共子序列
<p align='center'>
......@@ -144,67 +144,5 @@ else:
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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];
}
```
......@@ -10,8 +10,8 @@
![](../pictures/souyisou.png)
相关推荐:
* [动态规划设计:最大子数组](https://labuladong.gitbook.io/algo)
* [一文学会递归解题](https://labuladong.gitbook.io/algo)
* [动态规划设计:最大子数组](../动态规划系列/最大子数组.md)
* [一文学会递归解题](../投稿/一文学会递归解题.md)
读完本文,你不仅学会了算法套路,还可以顺便去 LeetCode 上拿下如下题目:
......@@ -19,7 +19,7 @@
**-----------**
也许有读者看了前文 [动态规划详解](https://labuladong.gitbook.io/algo),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
也许有读者看了前文 [动态规划详解](../动态规划系列/动态规划详解进阶.md),学会了动态规划的套路:找到了问题的「状态」,明确了 `dp` 数组/函数的含义,定义了 base case;但是不知道如何确定「选择」,也就是不到状态转移的关系,依然写不出动态规划解法,怎么办?
不要担心,动态规划的难点本来就在于寻找正确的状态转移方程,本文就借助经典的「最长递增子序列问题」来讲一讲设计动态规划的通用技巧:**数学归纳思想**
......@@ -43,7 +43,7 @@
**我们的定义是这样的:`dp[i]` 表示以 `nums[i]` 这个数结尾的最长递增子序列的长度。**
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](https://labuladong.gitbook.io/algo) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。
PS:为什么这样定义呢?这是解决子序列问题的一个套路,后文[动态规划之子序列问题解题模板](../动态规划系列/子序列问题模板.md) 总结了几种常见套路。你读完本章所有的动态规划问题,就会发现 `dp` 数组的定义方法也就那几种。
根据这个定义,我们就可以推出 base case:`dp[i]` 初始值为 1,因为以 `nums[i]` 结尾的最长递增子序列起码要包含它自己。
......@@ -164,7 +164,7 @@ public int lengthOfLIS(int[] nums) {
我们只要把处理扑克牌的过程编程写出来即可。每次处理一张扑克牌不是要找一个合适的牌堆顶来放吗,牌堆顶的牌不是**有序**吗,这就能用到二分查找了:用二分查找来搜索当前牌应放置的位置。
PS:旧文[二分查找算法详解](https://labuladong.gitbook.io/algo)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
PS:旧文[二分查找算法详解](../算法思维系列/二分查找详解.md)详细介绍了二分查找的细节及变体,这里就完美应用上了,如果没读过强烈建议阅读。
```java
public int lengthOfLIS(int[] nums) {
......@@ -212,94 +212,5 @@ public int lengthOfLIS(int[] nums) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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;
}
};
```
# 动态规划答疑篇
**学好算法全靠套路,认准 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;
当然,上面这个例子太简单了,不过请读者回顾一下,我们做动态规划问题,是不是一直在求各种最值,本质跟我们举的例子没啥区别,无非需要处理一下重叠子问题。
前文不[同定义不同解法](https://labuladong.gitbook.io/algo)[高楼扔鸡蛋进阶](https://labuladong.gitbook.io/algo) 就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
前文不[同定义不同解法](../动态规划系列/动态规划之四键键盘.md)[高楼扔鸡蛋进阶](../动态规划系列/高楼扔鸡蛋问题.md) 就展示了如何改造问题,不同的最优子结构,可能导致不同的解法和效率。
再举个常见但也十分简单的例子,求一棵二叉树的最大值,不难吧(简单起见,假设节点中的值都是非负数):
......@@ -154,7 +154,5 @@ for (int i = 1; i < m; i++)
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -292,7 +292,6 @@ bool dp(string& s, int i, string& p, int j) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
# 动态规划之子序列问题解题模板
**学好算法全靠套路,认准 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,7 +171,5 @@ int longestPalindromeSubseq(string s) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,labuladong 带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -292,7 +292,5 @@ while (lo < hi) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
# 经典动态规划问题:高楼扔鸡蛋
**学好算法全靠套路,认准 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)
```
这里就不展开其他解法了,留在下一篇文章 [高楼扔鸡蛋进阶](https://labuladong.gitbook.io/algo)
这里就不展开其他解法了,留在下一篇文章 [高楼扔鸡蛋进阶](../动态规划系列/高楼扔鸡蛋进阶.md)
我觉得吧,我们这种解法就够了:找状态,做选择,足够清晰易懂,可流程化,可举一反三。掌握这套框架学有余力的话,再去考虑那些奇技淫巧也不迟。
......@@ -258,7 +258,5 @@ def superEggDrop(self, K: int, N: int) -> int:
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -136,7 +136,5 @@ vector<int> findErrorNums(vector<int>& nums) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -343,37 +343,5 @@ class LRUCache {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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) # 最近访问的放到链表最后,维护好顺序
```
......@@ -175,44 +175,5 @@ int countPrimes(int n) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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;
}
};
```
......@@ -108,14 +108,8 @@ def deleteDuplicates(self, head: ListNode) -> ListNode:
return head
```
**_____________**
[上一篇:如何高效解决接雨水问题](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>
======其他语言代码======
\ No newline at end of file
[目录](https://labuladong.gitbook.io/algo#目录)
......@@ -145,7 +145,5 @@ $$ -->
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -230,7 +230,5 @@ private int distance(int[] intv) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
# 回溯算法团灭子集、排列、组合问题
**学好算法全靠套路,认准 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,7 +281,5 @@ void backtrack(int[] nums, LinkedList<Integer> track) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
# 如何寻找最长回文子串
**学好算法全靠套路,认准 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,7 +128,5 @@ string longestPalindrome(string s) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -208,102 +208,5 @@ if (l_max < r_max) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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;
}
}
```
\ No newline at end of file
......@@ -166,7 +166,5 @@ for (int i = 0; i < n; i++)
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -234,7 +234,5 @@ p.next = reverse(q);
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -165,7 +165,5 @@ boolean isSubsequence(String s, String t) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -129,7 +129,5 @@ public int missingNumber(int[] nums) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -146,7 +146,5 @@ int bulbSwitch(int n) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -153,7 +153,5 @@ ListNode reverseKGroup(ListNode head, int k) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</p>
======其他语言代码======
\ No newline at end of file
......@@ -109,54 +109,5 @@ char leftOf(char c) {
**本小抄即将出版,微信扫码关注公众号,后台回复「小抄」限时免费获取,回复「进群」可进刷题群一起刷题,带你搞定 LeetCode**
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
<img src="../pictures/table_qr2.jpg" width=500 >
</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();
}
```
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册