mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-10 20:40:39 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -144,15 +144,28 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
```python3
|
||||
class Solution:
|
||||
def removeElement(self, nums: List[int], val: int) -> int:
|
||||
i,n = 0,len(nums)
|
||||
for j in range(n):
|
||||
if nums[j] != val:
|
||||
nums[i] = nums[j]
|
||||
i += 1
|
||||
return i
|
||||
"""双指针法
|
||||
时间复杂度:O(n)
|
||||
空间复杂度:O(1)
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def removeElement(cls, nums: List[int], val: int) -> int:
|
||||
fast = slow = 0
|
||||
|
||||
while fast < len(nums):
|
||||
|
||||
if nums[fast] != val:
|
||||
nums[slow] = nums[fast]
|
||||
slow += 1
|
||||
|
||||
# 当 fast 指针遇到要删除的元素时停止赋值
|
||||
# slow 指针停止移动, fast 指针继续前进
|
||||
fast += 1
|
||||
|
||||
return slow
|
||||
```
|
||||
|
||||
|
||||
|
@ -311,6 +311,35 @@ class solution {
|
||||
}
|
||||
```
|
||||
|
||||
### 559.n叉树的最大深度
|
||||
```java
|
||||
class solution {
|
||||
/**
|
||||
* 迭代法,使用层序遍历
|
||||
*/
|
||||
public int maxDepth(Node root) {
|
||||
if (root == null) return 0;
|
||||
int depth = 0;
|
||||
Queue<Node> que = new LinkedList<>();
|
||||
que.offer(root);
|
||||
while (!que.isEmpty())
|
||||
{
|
||||
depth ++;
|
||||
int len = que.size();
|
||||
while (len > 0)
|
||||
{
|
||||
Node node = que.poll();
|
||||
for (int i = 0; i < node.children.size(); i++)
|
||||
if (node.children.get(i) != null)
|
||||
que.offer(node.children.get(i));
|
||||
len--;
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## python
|
||||
|
||||
### 104.二叉树的最大深度
|
||||
|
@ -198,6 +198,29 @@ var isAnagram = function(s, t) {
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
```Swift
|
||||
func isAnagram(_ s: String, _ t: String) -> Bool {
|
||||
if s.count != t.count {
|
||||
return false
|
||||
}
|
||||
var record = Array(repeating: 0, count: 26)
|
||||
let aUnicodeScalar = "a".unicodeScalars.first!.value
|
||||
for c in s.unicodeScalars {
|
||||
record[Int(c.value - aUnicodeScalar)] += 1
|
||||
}
|
||||
for c in t.unicodeScalars {
|
||||
record[Int(c.value - aUnicodeScalar)] -= 1
|
||||
}
|
||||
for value in record {
|
||||
if value != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
## 相关题目
|
||||
|
||||
* 383.赎金信
|
||||
|
@ -161,15 +161,9 @@ class Solution(object):
|
||||
# count=0
|
||||
# for x3 in nums3:
|
||||
# for x4 in nums4:
|
||||
# key = -x3-x4
|
||||
# value = hashmap.get(key)
|
||||
|
||||
# dict的get方法会返回None(key不存在)或者key对应的value
|
||||
# 所以如果value==0,就会继续执行or,count+0,否则就会直接加value
|
||||
# 这样就不用去写if判断了
|
||||
|
||||
# count += value or 0
|
||||
|
||||
# key = 0 - x3 - x4
|
||||
# value = hashmap[key] # 若差值(key)不存在,则value被赋值0
|
||||
# count += value
|
||||
# return count
|
||||
|
||||
```
|
||||
|
@ -10,6 +10,9 @@
|
||||
|
||||
# 649. Dota2 参议院
|
||||
|
||||
[力扣题目链接](https://leetcode-cn.com/problems/dota2-senate/)
|
||||
|
||||
|
||||
Dota2 的世界里有两个阵营:Radiant(天辉)和 Dire(夜魇)
|
||||
|
||||
Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的一项:
|
||||
@ -115,16 +118,102 @@ public:
|
||||
## Java
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public String predictPartyVictory(String senateStr) {
|
||||
// R = true表示本轮循环结束后,字符串里依然有R。D同理
|
||||
Boolean R = true, D = true;
|
||||
// 当flag大于0时,R在D前出现,R可以消灭D。当flag小于0时,D在R前出现,D可以消灭R
|
||||
int flag = 0;
|
||||
byte[] senate = senateStr.getBytes();
|
||||
while (R && D) { // 一旦R或者D为false,就结束循环,说明本轮结束后只剩下R或者D了
|
||||
R = false;
|
||||
D = false;
|
||||
for (int i = 0; i < senate.length; i++) {
|
||||
if (senate[i] == 'R') {
|
||||
if (flag < 0) senate[i] = 0; // 消灭R,R此时为false
|
||||
else R = true; // 如果没被消灭,本轮循环结束有R
|
||||
flag++;
|
||||
}
|
||||
if (senate[i] == 'D') {
|
||||
if (flag > 0) senate[i] = 0;
|
||||
else D = true;
|
||||
flag--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 循环结束之后,R和D只能有一个为true
|
||||
return R == true ? "Radiant" : "Dire";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Python
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def predictPartyVictory(self, senate: str) -> str:
|
||||
# R = true表示本轮循环结束后,字符串里依然有R。D同理
|
||||
R , D = True, True
|
||||
|
||||
# 当flag大于0时,R在D前出现,R可以消灭D。当flag小于0时,D在R前出现,D可以消灭R
|
||||
flag = 0
|
||||
|
||||
senate = list(senate)
|
||||
while R and D: # 一旦R或者D为false,就结束循环,说明本轮结束后只剩下R或者D了
|
||||
R = False
|
||||
D = False
|
||||
for i in range(len(senate)) :
|
||||
if senate[i] == 'R' :
|
||||
if flag < 0: senate[i] = '0' # 消灭R,R此时为false
|
||||
else: R = True # 如果没被消灭,本轮循环结束有R
|
||||
flag += 1
|
||||
if senate[i] == 'D':
|
||||
if flag > 0: senate[i] = '0'
|
||||
else: D = True
|
||||
flag -= 1
|
||||
# 循环结束之后,R和D只能有一个为true
|
||||
return "Radiant" if R else "Dire"
|
||||
```
|
||||
|
||||
## Go
|
||||
|
||||
```go
|
||||
|
||||
func predictPartyVictory(senateStr string) string {
|
||||
// R = true表示本轮循环结束后,字符串里依然有R。D同理
|
||||
R, D := true, true
|
||||
// 当flag大于0时,R在D前出现,R可以消灭D。当flag小于0时,D在R前出现,D可以消灭R
|
||||
flag := 0
|
||||
|
||||
senate := []byte(senateStr)
|
||||
for R && D { // 一旦R或者D为false,就结束循环,说明本轮结束后只剩下R或者D了
|
||||
R = false
|
||||
D = false
|
||||
for i := 0; i < len(senate); i++ {
|
||||
if senate[i] == 'R' {
|
||||
if flag < 0 {
|
||||
senate[i] = 0 // 消灭R,R此时为false
|
||||
} else {
|
||||
R = true // 如果没被消灭,本轮循环结束有R
|
||||
}
|
||||
flag++;
|
||||
}
|
||||
if (senate[i] == 'D') {
|
||||
if flag > 0 {
|
||||
senate[i] = 0
|
||||
} else {
|
||||
D = true
|
||||
}
|
||||
flag--
|
||||
}
|
||||
}
|
||||
}
|
||||
// 循环结束之后,R和D只能有一个为true
|
||||
if R {
|
||||
return "Radiant"
|
||||
}
|
||||
return "Dire";
|
||||
}
|
||||
```
|
||||
|
||||
## JavaScript
|
||||
|
@ -406,6 +406,49 @@ func search(nums: [Int], target: Int) -> Int {
|
||||
|
||||
```
|
||||
|
||||
**Rust:**
|
||||
|
||||
```rust
|
||||
# (版本一)左闭右闭区间
|
||||
|
||||
impl Solution {
|
||||
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
||||
let mut left:usize = 0;
|
||||
let mut right:usize = nums.len() - 1;
|
||||
while left as i32 <= right as i32{
|
||||
let mid = (left + right) / 2;
|
||||
if nums[mid] < target {
|
||||
left = mid + 1;
|
||||
} else if nums[mid] > target {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
return mid as i32;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
# (版本二)左闭右开区间
|
||||
|
||||
impl Solution {
|
||||
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
||||
let mut left:usize = 0;
|
||||
let mut right:usize = nums.len();
|
||||
while left < right {
|
||||
let mid = (left + right) / 2;
|
||||
if nums[mid] < target {
|
||||
left = mid + 1;
|
||||
} else if nums[mid] > target {
|
||||
right = mid;
|
||||
} else {
|
||||
return mid as i32;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
## 判断子序列
|
||||
|
||||
[动态规划:392.判断子序列](https://mp.weixin.qq.com/s/2pjT4B4fjfOx5iB6N6xyng) 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
|
||||
[动态规划:392.判断子序列](https://programmercarl.com/0392.判断子序列.html) 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
|
||||
|
||||
|
||||
这道题目 其实是可以用双指针或者贪心的的,但是我在开篇的时候就说了这是编辑距离的入门题目,因为从题意中我们也可以发现,只需要计算删除的情况,不用考虑增加和替换的情况。
|
||||
@ -33,9 +33,9 @@ else dp[i][j] = dp[i][j - 1];
|
||||
|
||||
## 不同的子序列
|
||||
|
||||
[动态规划:115.不同的子序列](https://mp.weixin.qq.com/s/1SULY2XVSROtk_hsoVLu8A) 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
|
||||
[动态规划:115.不同的子序列](https://programmercarl.com/0115.不同的子序列.html) 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
|
||||
|
||||
本题虽然也只有删除操作,不用考虑替换增加之类的,但相对于[动态规划:392.判断子序列](https://mp.weixin.qq.com/s/2pjT4B4fjfOx5iB6N6xyng)就有难度了,这道题目双指针法可就做不了。
|
||||
本题虽然也只有删除操作,不用考虑替换增加之类的,但相对于[动态规划:392.判断子序列](https://programmercarl.com/0392.判断子序列.html)就有难度了,这道题目双指针法可就做不了。
|
||||
|
||||
|
||||
当s[i - 1] 与 t[j - 1]相等时,dp[i][j]可以有两部分组成。
|
||||
@ -68,9 +68,9 @@ if (s[i - 1] == t[j - 1]) {
|
||||
|
||||
## 两个字符串的删除操作
|
||||
|
||||
[动态规划:583.两个字符串的删除操作](https://mp.weixin.qq.com/s/a8BerpqSf76DCqkPDJrpYg)给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
|
||||
[动态规划:583.两个字符串的删除操作](https://programmercarl.com/0583.两个字符串的删除操作.html)给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
|
||||
|
||||
本题和[动态规划:115.不同的子序列](https://mp.weixin.qq.com/s/1SULY2XVSROtk_hsoVLu8A)相比,其实就是两个字符串可以都可以删除了,情况虽说复杂一些,但整体思路是不变的。
|
||||
本题和[动态规划:115.不同的子序列](https://programmercarl.com/0115.不同的子序列.html)相比,其实就是两个字符串可以都可以删除了,情况虽说复杂一些,但整体思路是不变的。
|
||||
|
||||
|
||||
* 当word1[i - 1] 与 word2[j - 1]相同的时候
|
||||
@ -100,10 +100,10 @@ if (word1[i - 1] == word2[j - 1]) {
|
||||
|
||||
## 编辑距离
|
||||
|
||||
[动态规划:72.编辑距离](https://mp.weixin.qq.com/s/8aG71XjSgZG6kZbiAdkJnQ) 给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
|
||||
[动态规划:72.编辑距离](https://programmercarl.com/0072.编辑距离.html) 给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
|
||||
|
||||
|
||||
编辑距离终于来了,**有了前面三道题目的铺垫,应该有思路了**,本题是两个字符串可以增删改,比 [动态规划:判断子序列](https://mp.weixin.qq.com/s/2pjT4B4fjfOx5iB6N6xyng),[动态规划:不同的子序列](https://mp.weixin.qq.com/s/1SULY2XVSROtk_hsoVLu8A),[动态规划:两个字符串的删除操作](https://mp.weixin.qq.com/s/a8BerpqSf76DCqkPDJrpYg)都要复杂的多。
|
||||
编辑距离终于来了,**有了前面三道题目的铺垫,应该有思路了**,本题是两个字符串可以增删改,比 [动态规划:判断子序列](https://programmercarl.com/0392.判断子序列.html),[动态规划:不同的子序列](https://programmercarl.com/0115.不同的子序列.html),[动态规划:两个字符串的删除操作](https://programmercarl.com/0583.两个字符串的删除操作.html)都要复杂的多。
|
||||
|
||||
|
||||
在确定递推公式的时候,首先要考虑清楚编辑的几种操作,整理如下:
|
||||
@ -161,7 +161,7 @@ else {
|
||||
|
||||
## 总结
|
||||
|
||||
心思的录友应该会发现我用了三道题做铺垫,才最后引出了[动态规划:72.编辑距离](https://mp.weixin.qq.com/s/8aG71XjSgZG6kZbiAdkJnQ) ,Carl的良苦用心呀,你们体会到了嘛!
|
||||
心思的录友应该会发现我用了三道题做铺垫,才最后引出了[动态规划:72.编辑距离](https://programmercarl.com/0072.编辑距离.html) ,Carl的良苦用心呀,你们体会到了嘛!
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
@ -105,7 +105,7 @@
|
||||
|
||||
可能是我写总结写习惯了,什么文章都要有一个总结,哈哈,那么我就总结一下。
|
||||
|
||||
北京的互联网氛围绝对是最好的(暂不讨论户口和房价问题),大家如果看了[深圳原来有这么多互联网公司,你都知道么?](https://mp.weixin.qq.com/s/3VJHF2zNohBwDBxARFIn-Q)这篇之后,**会发现北京互联网外企和二线互联网公司数量多的优势,在深圳的互联网公司断档比较严重,如果去不了为数不多的一线公司,可选择的余地就非常少了,而北京选择的余地就很多!**
|
||||
北京的互联网氛围绝对是最好的(暂不讨论户口和房价问题),大家如果看了[深圳原来有这么多互联网公司,你都知道么?](https://programmercarl.com/前序/深圳互联网公司总结.html)这篇之后,**会发现北京互联网外企和二线互联网公司数量多的优势,在深圳的互联网公司断档比较严重,如果去不了为数不多的一线公司,可选择的余地就非常少了,而北京选择的余地就很多!**
|
||||
|
||||
相对来说,深圳的硬件企业更多一些,因为珠三角制造业配套比较完善。而大多数互联网公司其实就是媒体公司,当然要靠近政治文化中心,这也是有原因的。
|
||||
|
||||
|
@ -46,7 +46,7 @@ for (int i = 0; i < a.size(); i++) {
|
||||
|
||||
# 要不要使用库函数
|
||||
|
||||
在文章[344.反转字符串](https://mp.weixin.qq.com/s/_rNm66OJVl92gBDIbGpA3w)中强调了**打基础的时候,不要太迷恋于库函数。**
|
||||
在文章[344.反转字符串](https://programmercarl.com/0344.反转字符串.html)中强调了**打基础的时候,不要太迷恋于库函数。**
|
||||
|
||||
甚至一些同学习惯于调用substr,split,reverse之类的库函数,却不知道其实现原理,也不知道其时间复杂度,这样实现出来的代码,如果在面试现场,面试官问:“分析其时间复杂度”的话,一定会一脸懵逼!
|
||||
|
||||
@ -57,15 +57,15 @@ for (int i = 0; i < a.size(); i++) {
|
||||
# 双指针法
|
||||
|
||||
|
||||
在[344.反转字符串](https://mp.weixin.qq.com/s/_rNm66OJVl92gBDIbGpA3w) ,我们使用双指针法实现了反转字符串的操作,**双指针法在数组,链表和字符串中很常用。**
|
||||
在[344.反转字符串](https://programmercarl.com/0344.反转字符串.html) ,我们使用双指针法实现了反转字符串的操作,**双指针法在数组,链表和字符串中很常用。**
|
||||
|
||||
接着在[字符串:替换空格](https://mp.weixin.qq.com/s/69HNjR4apcRSAo_KyknPjA),同样还是使用双指针法在时间复杂度O(n)的情况下完成替换空格。
|
||||
接着在[字符串:替换空格](https://programmercarl.com/剑指Offer05.替换空格.html),同样还是使用双指针法在时间复杂度O(n)的情况下完成替换空格。
|
||||
|
||||
**其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。**
|
||||
|
||||
那么针对数组删除操作的问题,其实在[27. 移除元素](https://mp.weixin.qq.com/s/RMkulE4NIb6XsSX83ra-Ww)中就已经提到了使用双指针法进行移除操作。
|
||||
那么针对数组删除操作的问题,其实在[27. 移除元素](https://programmercarl.com/0027.移除元素.html)中就已经提到了使用双指针法进行移除操作。
|
||||
|
||||
同样的道理在[151.翻转字符串里的单词](https://mp.weixin.qq.com/s/4j6vPFHkFAXnQhmSkq2X9g)中我们使用O(n)的时间复杂度,完成了删除冗余空格。
|
||||
同样的道理在[151.翻转字符串里的单词](https://programmercarl.com/0151.翻转字符串里的单词.html)中我们使用O(n)的时间复杂度,完成了删除冗余空格。
|
||||
|
||||
一些同学会使用for循环里调用库函数erase来移除元素,这其实是O(n^2)的操作,因为erase就是O(n)的操作,所以这也是典型的不知道库函数的时间复杂度,上来就用的案例了。
|
||||
|
||||
@ -73,7 +73,7 @@ for (int i = 0; i < a.size(); i++) {
|
||||
|
||||
在反转上还可以在加一些玩法,其实考察的是对代码的掌控能力。
|
||||
|
||||
[541. 反转字符串II](https://mp.weixin.qq.com/s/pzXt6PQ029y7bJ9YZB2mVQ)中,一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。
|
||||
[541. 反转字符串II](https://programmercarl.com/0541.反转字符串II.html)中,一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。
|
||||
|
||||
其实**当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章**。
|
||||
|
||||
@ -81,26 +81,26 @@ for (int i = 0; i < a.size(); i++) {
|
||||
|
||||
因为要找的也就是每2 * k 区间的起点,这样写程序会高效很多。
|
||||
|
||||
在[151.翻转字符串里的单词](https://mp.weixin.qq.com/s/4j6vPFHkFAXnQhmSkq2X9g)中要求翻转字符串里的单词,这道题目可以说是综合考察了字符串的多种操作。是考察字符串的好题。
|
||||
在[151.翻转字符串里的单词](https://programmercarl.com/0151.翻转字符串里的单词.html)中要求翻转字符串里的单词,这道题目可以说是综合考察了字符串的多种操作。是考察字符串的好题。
|
||||
|
||||
这道题目通过 **先整体反转再局部反转**,实现了反转字符串里的单词。
|
||||
|
||||
后来发现反转字符串还有一个牛逼的用处,就是达到左旋的效果。
|
||||
|
||||
在[字符串:反转个字符串还有这个用处?](https://mp.weixin.qq.com/s/Px_L-RfT2b_jXKcNmccPsw)中,我们通过**先局部反转再整体反转**达到了左旋的效果。
|
||||
在[字符串:反转个字符串还有这个用处?](https://programmercarl.com/剑指Offer58-II.左旋转字符串.html)中,我们通过**先局部反转再整体反转**达到了左旋的效果。
|
||||
|
||||
# KMP
|
||||
|
||||
KMP的主要思想是**当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。**
|
||||
|
||||
KMP的精髓所在就是前缀表,在[KMP精讲](https://mp.weixin.qq.com/s/MoRBHbS4hQXn7LcPdmHmIg)中提到了,什么是KMP,什么是前缀表,以及为什么要用前缀表。
|
||||
KMP的精髓所在就是前缀表,在[KMP精讲](https://programmercarl.com/0028.实现strStr.html)中提到了,什么是KMP,什么是前缀表,以及为什么要用前缀表。
|
||||
|
||||
前缀表:起始位置到下表i之前(包括i)的子串中,有多大长度的相同前缀后缀。
|
||||
|
||||
那么使用KMP可以解决两类经典问题:
|
||||
|
||||
1. 匹配问题:[28. 实现 strStr()](https://mp.weixin.qq.com/s/MoRBHbS4hQXn7LcPdmHmIg)
|
||||
2. 重复子串问题:[459.重复的子字符串](https://mp.weixin.qq.com/s/32Pve4j8IWvdgxYEZdTeFg)
|
||||
1. 匹配问题:[28. 实现 strStr()](https://programmercarl.com/0028.实现strStr.html)
|
||||
2. 重复子串问题:[459.重复的子字符串](https://programmercarl.com/0459.重复的子字符串.html)
|
||||
|
||||
再一次强调了什么是前缀,什么是后缀,什么又是最长相等前后缀。
|
||||
|
||||
@ -108,7 +108,7 @@ KMP的精髓所在就是前缀表,在[KMP精讲](https://mp.weixin.qq.com/s/Mo
|
||||
|
||||
后缀:指不包含第一个字符的所有以最后一个字符结尾的连续子串。
|
||||
|
||||
然后**针对前缀表到底要不要减一,这其实是不同KMP实现的方式**,我们在[KMP精讲](https://mp.weixin.qq.com/s/MoRBHbS4hQXn7LcPdmHmIg)中针对之前两个问题,分别给出了两个不同版本的的KMP实现。
|
||||
然后**针对前缀表到底要不要减一,这其实是不同KMP实现的方式**,我们在[KMP精讲](https://programmercarl.com/0028.实现strStr.html)中针对之前两个问题,分别给出了两个不同版本的的KMP实现。
|
||||
|
||||
其中主要**理解j=next[x]这一步最为关键!**
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
# 栈与队列的理论基础
|
||||
|
||||
首先我们在[栈与队列:来看看栈和队列不为人知的一面](https://mp.weixin.qq.com/s/VZRjOccyE09aE-MgLbCMjQ)中讲解了栈和队列的理论基础。
|
||||
首先我们在[栈与队列:来看看栈和队列不为人知的一面](https://programmercarl.com/栈与队列理论基础.html)中讲解了栈和队列的理论基础。
|
||||
|
||||
里面提到了灵魂四问:
|
||||
|
||||
@ -33,9 +33,9 @@
|
||||
|
||||
大家还是要多多重视起来!
|
||||
|
||||
了解了栈与队列基础之后,那么可以用[栈与队列:栈实现队列](https://mp.weixin.qq.com/s/P6tupDwRFi6Ay-L7DT4NVg) 和 [栈与队列:队列实现栈](https://mp.weixin.qq.com/s/yzn6ktUlL-vRG3-m5a8_Yw) 来练习一下栈与队列的基本操作。
|
||||
了解了栈与队列基础之后,那么可以用[栈与队列:栈实现队列](https://programmercarl.com/0232.用栈实现队列.html) 和 [栈与队列:队列实现栈](https://programmercarl.com/0225.用队列实现栈.html) 来练习一下栈与队列的基本操作。
|
||||
|
||||
值得一提的是,用[栈与队列:用队列实现栈还有点别扭](https://mp.weixin.qq.com/s/yzn6ktUlL-vRG3-m5a8_Yw)中,其实只用一个队列就够了。
|
||||
值得一提的是,用[栈与队列:用队列实现栈还有点别扭](https://programmercarl.com/0225.用队列实现栈.html)中,其实只用一个队列就够了。
|
||||
|
||||
**一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。**
|
||||
|
||||
@ -63,7 +63,7 @@ cd a/b/c/../../
|
||||
|
||||
## 括号匹配问题
|
||||
|
||||
在[栈与队列:系统中处处都是栈的应用](https://mp.weixin.qq.com/s/nLlmPMsDCIWSqAtr0jbrpQ)中我们讲解了括号匹配问题。
|
||||
在[栈与队列:系统中处处都是栈的应用](https://programmercarl.com/0020.有效的括号.html)中我们讲解了括号匹配问题。
|
||||
|
||||
**括号匹配是使用栈解决的经典问题。**
|
||||
|
||||
@ -79,23 +79,23 @@ cd a/b/c/../../
|
||||
|
||||
## 字符串去重问题
|
||||
|
||||
在[栈与队列:匹配问题都是栈的强项](https://mp.weixin.qq.com/s/eynAEbUbZoAWrk0ZlEugqg)中讲解了字符串去重问题。
|
||||
在[栈与队列:匹配问题都是栈的强项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)中讲解了字符串去重问题。
|
||||
1047. 删除字符串中的所有相邻重复项
|
||||
|
||||
思路就是可以把字符串顺序放到一个栈中,然后如果相同的话 栈就弹出,这样最后栈里剩下的元素都是相邻不相同的元素了。
|
||||
|
||||
## 逆波兰表达式问题
|
||||
|
||||
在[栈与队列:有没有想过计算机是如何处理表达式的?](https://mp.weixin.qq.com/s/hneh2nnLT91rR8ms2fm_kw)中讲解了求逆波兰表达式。
|
||||
在[栈与队列:有没有想过计算机是如何处理表达式的?](https://programmercarl.com/0150.逆波兰表达式求值.html)中讲解了求逆波兰表达式。
|
||||
|
||||
本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么**这岂不就是一个相邻字符串消除的过程,和[栈与队列:匹配问题都是栈的强项](https://mp.weixin.qq.com/s/eynAEbUbZoAWrk0ZlEugqg)中的对对碰游戏是不是就非常像了。**
|
||||
本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么**这岂不就是一个相邻字符串消除的过程,和[栈与队列:匹配问题都是栈的强项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)中的对对碰游戏是不是就非常像了。**
|
||||
|
||||
|
||||
# 队列的经典题目
|
||||
|
||||
## 滑动窗口最大值问题
|
||||
|
||||
在[栈与队列:滑动窗口里求最大值引出一个重要数据结构](https://mp.weixin.qq.com/s/8c6l2bO74xyMjph09gQtpA)中讲解了一种数据结构:单调队列。
|
||||
在[栈与队列:滑动窗口里求最大值引出一个重要数据结构](https://programmercarl.com/0239.滑动窗口最大值.html)中讲解了一种数据结构:单调队列。
|
||||
|
||||
这道题目还是比较绕的,如果第一次遇到这种题目,需要反复琢磨琢磨
|
||||
|
||||
@ -123,7 +123,7 @@ cd a/b/c/../../
|
||||
|
||||
## 求前 K 个高频元素
|
||||
|
||||
在[栈与队列:求前 K 个高频元素和队列有啥关系?](https://mp.weixin.qq.com/s/8hMwxoE_BQRbzCc7CA8rng)中讲解了求前 K 个高频元素。
|
||||
在[栈与队列:求前 K 个高频元素和队列有啥关系?](https://programmercarl.com/0347.前K个高频元素.html)中讲解了求前 K 个高频元素。
|
||||
|
||||
通过求前 K 个高频元素,引出另一种队列就是**优先级队列**。
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
## 贪心理论基础
|
||||
|
||||
在贪心系列开篇词[关于贪心算法,你该了解这些!](https://mp.weixin.qq.com/s/O935TaoHE9Eexwe_vSbRAg)中,我们就讲解了大家对贪心的普遍疑惑。
|
||||
在贪心系列开篇词[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html)中,我们就讲解了大家对贪心的普遍疑惑。
|
||||
|
||||
1. 贪心很简单,就是常识?
|
||||
|
||||
@ -48,42 +48,42 @@ Carl个人认为:如果找出局部最优并可以推出全局最优,就是
|
||||
|
||||
就像是 要用一下 1 + 1 = 2,没有必要再证明一下 1 + 1 究竟为什么等于 2。(例子极端了点,但是这个道理)
|
||||
|
||||
相信大家读完[关于贪心算法,你该了解这些!](https://mp.weixin.qq.com/s/O935TaoHE9Eexwe_vSbRAg),就对贪心有了一个基本的认识了。
|
||||
相信大家读完[关于贪心算法,你该了解这些!](https://programmercarl.com/贪心算法理论基础.html),就对贪心有了一个基本的认识了。
|
||||
|
||||
|
||||
## 贪心简单题
|
||||
|
||||
以下三道题目就是简单题,大家会发现贪心感觉就是常识。是的,如下三道题目,就是靠常识,但我都具体分析了局部最优是什么,全局最优是什么,贪心也要贪的有理有据!
|
||||
|
||||
* [贪心算法:分发饼干](https://mp.weixin.qq.com/s/YSuLIAYyRGlyxbp9BNC1uw)
|
||||
* [贪心算法:K次取反后最大化的数组和](https://mp.weixin.qq.com/s/dMTzBBVllRm_Z0aaWvYazA)
|
||||
* [贪心算法:柠檬水找零](https://mp.weixin.qq.com/s/0kT4P-hzY7H6Ae0kjQqnZg)
|
||||
* [贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html)
|
||||
* [贪心算法:K次取反后最大化的数组和](https://programmercarl.com/1005.K次取反后最大化的数组和.html)
|
||||
* [贪心算法:柠檬水找零](https://programmercarl.com/0860.柠檬水找零.html)
|
||||
|
||||
|
||||
## 贪心中等题
|
||||
|
||||
贪心中等题,靠常识可能就有点想不出来了。开始初现贪心算法的难度与巧妙之处。
|
||||
|
||||
* [贪心算法:摆动序列](https://mp.weixin.qq.com/s/Xytl05kX8LZZ1iWWqjMoHA)
|
||||
* [贪心算法:单调递增的数字](https://mp.weixin.qq.com/s/TAKO9qPYiv6KdMlqNq_ncg)
|
||||
* [贪心算法:摆动序列](https://programmercarl.com/0376.摆动序列.html)
|
||||
* [贪心算法:单调递增的数字](https://programmercarl.com/0738.单调递增的数字.html)
|
||||
|
||||
### 贪心解决股票问题
|
||||
|
||||
大家都知道股票系列问题是动规的专长,其实用贪心也可以解决,而且还不止就这两道题目,但这两道比较典型,我就拿来单独说一说
|
||||
|
||||
* [贪心算法:买卖股票的最佳时机II](https://mp.weixin.qq.com/s/VsTFA6U96l18Wntjcg3fcg)
|
||||
* [贪心算法:买卖股票的最佳时机含手续费](https://mp.weixin.qq.com/s/olWrUuDEYw2Jx5rMeG7XAg)
|
||||
* [贪心算法:买卖股票的最佳时机II](https://programmercarl.com/0122.买卖股票的最佳时机II.html)
|
||||
* [贪心算法:买卖股票的最佳时机含手续费](https://programmercarl.com/0714.买卖股票的最佳时机含手续费.html)
|
||||
|
||||
### 两个维度权衡问题
|
||||
|
||||
在出现两个维度相互影响的情况时,两边一起考虑一定会顾此失彼,要先确定一个维度,再确定另一个一个维度。
|
||||
|
||||
* [贪心算法:分发糖果](https://mp.weixin.qq.com/s/8MwlgFfvaNYmjGwjuMlETQ)
|
||||
* [贪心算法:根据身高重建队列](https://mp.weixin.qq.com/s/-2TgZVdOwS-DvtbjjDEbfw)
|
||||
* [贪心算法:分发糖果](https://programmercarl.com/0135.分发糖果.html)
|
||||
* [贪心算法:根据身高重建队列](https://programmercarl.com/0406.根据身高重建队列.html)
|
||||
|
||||
在讲解本题的过程中,还强调了编程语言的重要性,模拟插队的时候,使用C++中的list(链表)替代了vector(动态数组),效率会高很多。
|
||||
|
||||
所以在[贪心算法:根据身高重建队列(续集)](https://mp.weixin.qq.com/s/K-pRN0lzR-iZhoi-1FgbSQ)详细讲解了,为什么用list(链表)更快!
|
||||
所以在[贪心算法:根据身高重建队列(续集)](https://programmercarl.com/根据身高重建队列(vector原理讲解).html)详细讲解了,为什么用list(链表)更快!
|
||||
|
||||
**大家也要掌握自己所用的编程语言,理解其内部实现机制,这样才能写出高效的算法!**
|
||||
|
||||
@ -95,21 +95,20 @@ Carl个人认为:如果找出局部最优并可以推出全局最优,就是
|
||||
|
||||
关于区间问题,大家应该印象深刻,有一周我们专门讲解的区间问题,各种覆盖各种去重。
|
||||
|
||||
* [贪心算法:跳跃游戏](https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA)
|
||||
* [贪心算法:跳跃游戏II](https://mp.weixin.qq.com/s/kJBcsJ46DKCSjT19pxrNYg)
|
||||
* [贪心算法:用最少数量的箭引爆气球](https://mp.weixin.qq.com/s/HxVAJ6INMfNKiGwI88-RFw)
|
||||
* [贪心算法:无重叠区间](https://mp.weixin.qq.com/s/oFOEoW-13Bm4mik-aqAOmw)
|
||||
* [贪心算法:划分字母区间](https://mp.weixin.qq.com/s/pdX4JwV1AOpc_m90EcO2Hw)
|
||||
* [贪心算法:合并区间](https://mp.weixin.qq.com/s/royhzEM5tOkUFwUGrNStpw)
|
||||
* [贪心算法:跳跃游戏](https://programmercarl.com/0055.跳跃游戏.html)
|
||||
* [贪心算法:跳跃游戏II](https://programmercarl.com/0045.跳跃游戏II.html)
|
||||
* [贪心算法:用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)
|
||||
* [贪心算法:无重叠区间](https://programmercarl.com/0435.无重叠区间.html)
|
||||
* [贪心算法:划分字母区间](https://programmercarl.com/0763.划分字母区间.html)
|
||||
* [贪心算法:合并区间](https://programmercarl.com/0056.合并区间.html)
|
||||
|
||||
### 其他难题
|
||||
|
||||
[贪心算法:最大子序和](https://mp.weixin.qq.com/s/DrjIQy6ouKbpletQr0g1Fg) 其实是动态规划的题目,但贪心性能更优,很多同学也是第一次发现贪心能比动规更优的题目。
|
||||
[贪心算法:最大子序和](https://programmercarl.com/0053.最大子序和.html) 其实是动态规划的题目,但贪心性能更优,很多同学也是第一次发现贪心能比动规更优的题目。
|
||||
|
||||
[贪心算法:加油站](https://programmercarl.com/0134.加油站.html)可能以为是一道模拟题,但就算模拟其实也不简单,需要把while用的很娴熟。但其实是可以使用贪心给时间复杂度降低一个数量级。
|
||||
|
||||
[贪心算法:加油站](https://mp.weixin.qq.com/s/aDbiNuEZIhy6YKgQXvKELw)可能以为是一道模拟题,但就算模拟其实也不简单,需要把while用的很娴熟。但其实是可以使用贪心给时间复杂度降低一个数量级。
|
||||
|
||||
最后贪心系列压轴题目[贪心算法:我要监控二叉树!](https://mp.weixin.qq.com/s/kCxlLLjWKaE6nifHC3UL2Q),不仅贪心的思路不好想,而且需要对二叉树的操作特别娴熟,这就是典型的交叉类难题了。
|
||||
最后贪心系列压轴题目[贪心算法:我要监控二叉树!](https://programmercarl.com/0968.监控二叉树.html),不仅贪心的思路不好想,而且需要对二叉树的操作特别娴熟,这就是典型的交叉类难题了。
|
||||
|
||||
|
||||
## 贪心每周总结
|
||||
@ -120,10 +119,10 @@ Carl个人认为:如果找出局部最优并可以推出全局最优,就是
|
||||
|
||||
所以周总结一定要看!
|
||||
|
||||
* [本周小结!(贪心算法系列一)](https://mp.weixin.qq.com/s/KQ2caT9GoVXgB1t2ExPncQ)
|
||||
* [本周小结!(贪心算法系列二)](https://mp.weixin.qq.com/s/RiQri-4rP9abFmq_mlXNiQ)
|
||||
* [本周小结!(贪心算法系列三)](https://mp.weixin.qq.com/s/JfeuK6KgmifscXdpEyIm-g)
|
||||
* [本周小结!(贪心算法系列四)](https://mp.weixin.qq.com/s/zAMHT6JfB19ZSJNP713CAQ)
|
||||
* [本周小结!(贪心算法系列一)](https://programmercarl.com/周总结/20201126贪心周末总结.html)
|
||||
* [本周小结!(贪心算法系列二)](https://programmercarl.com/周总结/20201203贪心周末总结.html)
|
||||
* [本周小结!(贪心算法系列三)](https://programmercarl.com/周总结/20201217贪心周末总结.html)
|
||||
* [本周小结!(贪心算法系列四)](https://programmercarl.com/周总结/20201224贪心周末总结.html)
|
||||
|
||||
## 总结
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
**那么刷题的时候什么时候真的需要数学推导呢?**
|
||||
|
||||
例如这道题目:[链表:环找到了,那入口呢?](https://mp.weixin.qq.com/s/_QVP3IkRZWx9zIpQRgajzA),这道题不用数学推导一下,就找不出环的起始位置,想试一下就不知道怎么试,这种题目确实需要数学简单推导一下。
|
||||
例如这道题目:[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html),这道题不用数学推导一下,就找不出环的起始位置,想试一下就不知道怎么试,这种题目确实需要数学简单推导一下。
|
||||
|
||||
## 贪心一般解题步骤
|
||||
|
||||
|
Reference in New Issue
Block a user