diff --git a/README.md b/README.md index a31629607f..dd70d8cb6b 100644 --- a/README.md +++ b/README.md @@ -387,10 +387,26 @@ 4. [单调栈:42.接雨水](./problems/0042.接雨水.md) 5. [单调栈:84.柱状图中最大的矩形](./problems/0084.柱状图中最大的矩形.md) -(持续更新中....) ## 图论 +通知:开始更新图论内容,图论部分还没有其他语言版本,欢迎录友们提交PR,成为contributor + +### 深搜广搜 + +* [图论:深度优先搜索理论基础](./problems/图论深搜理论基础.md) +* [图论:797.所有可能的路径](./problems/0797.所有可能的路径.md) +* [图论:广度优先搜索理论基础](./problems/图论广索理论基础.md) +* [图论:200.岛屿数量.深搜版](./problems/0200.岛屿数量.深搜版.md) +* [图论:200.岛屿数量.广搜版](./problems/0200.岛屿数量.广搜版.md) +* [图论:695.岛屿的最大面积](./problems/0695.岛屿的最大面积.md) +* [图论:1020.飞地的数量](./problems/1020.飞地的数量.md) +* [图论:130.被围绕的区域](./problems/0130.被围绕的区域.md) +* [图论:417.太平洋大西洋水流问题](./problems/0417.太平洋大西洋水流问题.md) + +(持续更新中....) + + ## 十大排序 ## 数论 @@ -492,7 +508,7 @@ 大家好,我是程序员Carl,哈工大师兄,《代码随想录》作者,先后在腾讯和百度从事后端技术研发,CSDN博客专家。对算法和C++后端技术有一定的见解,利用工作之余重新刷leetcode。 -加入「代码随想录」刷题小分队(微信群),可以扫下方二维码加我微信。 +加入「代码随想录」刷题小分队(微信群),可以扫下方二维码,加代码随想录客服微信。 如果是已工作,备注:姓名-城市-岗位-组队刷题。如果学生,备注:姓名-学校-年级-组队刷题。**备注没有自我介绍不通过哦** diff --git "a/problems/0019.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" "b/problems/0019.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" index c6f5bfc781..84eac96b84 100644 --- "a/problems/0019.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" +++ "b/problems/0019.\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271.md" @@ -412,6 +412,28 @@ struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { ``` +C#: +```csharp +public class Solution { + public ListNode RemoveNthFromEnd(ListNode head, int n) { + ListNode dummpHead = new ListNode(0); + dummpHead.next = head; + var fastNode = dummpHead; + var slowNode = dummpHead; + while(n-- != 0 && fastNode != null) + { + fastNode = fastNode.next; + } + while(fastNode.next != null) + { + fastNode = fastNode.next; + slowNode = slowNode.next; + } + slowNode.next = slowNode.next.next; + return dummpHead.next; + } +} +```
diff --git "a/problems/0045.\350\267\263\350\267\203\346\270\270\346\210\217II.md" "b/problems/0045.\350\267\263\350\267\203\346\270\270\346\210\217II.md"
index 8a9395824c..2f0349b2cc 100644
--- "a/problems/0045.\350\267\263\350\267\203\346\270\270\346\210\217II.md"
+++ "b/problems/0045.\350\267\263\350\267\203\346\270\270\346\210\217II.md"
@@ -205,66 +205,81 @@ class Solution {
```
### Python
-
+贪心(版本一)
```python
class Solution:
- def jump(self, nums: List[int]) -> int:
- if len(nums) == 1: return 0
- ans = 0
- curDistance = 0
- nextDistance = 0
+ def jump(self, nums):
+ if len(nums) == 1:
+ return 0
+
+ cur_distance = 0 # 当前覆盖最远距离下标
+ ans = 0 # 记录走的最大步数
+ next_distance = 0 # 下一步覆盖最远距离下标
+
for i in range(len(nums)):
- nextDistance = max(i + nums[i], nextDistance)
- if i == curDistance:
- if curDistance != len(nums) - 1:
- ans += 1
- curDistance = nextDistance
- if nextDistance >= len(nums) - 1: break
+ next_distance = max(nums[i] + i, next_distance) # 更新下一步覆盖最远距离下标
+ if i == cur_distance: # 遇到当前覆盖最远距离下标
+ ans += 1 # 需要走下一步
+ cur_distance = next_distance # 更新当前覆盖最远距离下标(相当于加油了)
+ if next_distance >= len(nums) - 1: # 当前覆盖最远距离达到数组末尾,不用再做ans++操作,直接结束
+ break
+
return ans
+
```
+贪心(版本二)
```python
-# 贪心版本二
class Solution:
- def jump(self, nums: List[int]) -> int:
- if len(nums) == 1:
- return 0
- curDistance, nextDistance = 0, 0
- step = 0
- for i in range(len(nums)-1):
- nextDistance = max(nextDistance, nums[i]+i)
- if i == curDistance:
- curDistance = nextDistance
- step += 1
- return step
+ def jump(self, nums):
+ cur_distance = 0 # 当前覆盖的最远距离下标
+ ans = 0 # 记录走的最大步数
+ next_distance = 0 # 下一步覆盖的最远距离下标
+
+ for i in range(len(nums) - 1): # 注意这里是小于len(nums) - 1,这是关键所在
+ next_distance = max(nums[i] + i, next_distance) # 更新下一步覆盖的最远距离下标
+ if i == cur_distance: # 遇到当前覆盖的最远距离下标
+ cur_distance = next_distance # 更新当前覆盖的最远距离下标
+ ans += 1
+
+ return ans
+
```
+贪心(版本三) 类似‘55-跳跃游戏’写法
+
```python
-# 贪心版本三 - 类似‘55-跳跃游戏’写法
class Solution:
def jump(self, nums) -> int:
- if len(nums)==1: return 0
- i = 0
- count = 0
- cover = 0
- while i<=cover:
- for i in range(i,cover+1):
- cover = max(nums[i]+i,cover)
- if cover>=len(nums)-1: return count+1
- count+=1
+ if len(nums)==1: # 如果数组只有一个元素,不需要跳跃,步数为0
+ return 0
-```
+ i = 0 # 当前位置
+ count = 0 # 步数计数器
+ cover = 0 # 当前能够覆盖的最远距离
+
+ while i <= cover: # 当前位置小于等于当前能够覆盖的最远距离时循环
+ for i in range(i, cover+1): # 遍历从当前位置到当前能够覆盖的最远距离之间的所有位置
+ cover = max(nums[i]+i, cover) # 更新当前能够覆盖的最远距离
+ if cover >= len(nums)-1: # 如果当前能够覆盖的最远距离达到或超过数组的最后一个位置,直接返回步数+1
+ return count+1
+ count += 1 # 每一轮遍历结束后,步数+1
+
+```
+动态规划
```python
-# 动态规划做法
class Solution:
def jump(self, nums: List[int]) -> int:
- result = [10**4+1]*len(nums)
- result[0]=0
- for i in range(len(nums)):
- for j in range(nums[i]+1):
- if i+j
diff --git "a/problems/0096.\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md" "b/problems/0096.\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md"
index 9f41906d27..368a5747b1 100644
--- "a/problems/0096.\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md"
+++ "b/problems/0096.\344\270\215\345\220\214\347\232\204\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.md"
@@ -197,12 +197,13 @@ class Solution {
```python
class Solution:
def numTrees(self, n: int) -> int:
- dp = [0] * (n + 1)
- dp[0], dp[1] = 1, 1
- for i in range(2, n + 1):
- for j in range(1, i + 1):
- dp[i] += dp[j - 1] * dp[i - j]
- return dp[-1]
+ dp = [0] * (n + 1) # 创建一个长度为n+1的数组,初始化为0
+ dp[0] = 1 # 当n为0时,只有一种情况,即空树,所以dp[0] = 1
+ for i in range(1, n + 1): # 遍历从1到n的每个数字
+ for j in range(1, i + 1): # 对于每个数字i,计算以i为根节点的二叉搜索树的数量
+ dp[i] += dp[j - 1] * dp[i - j] # 利用动态规划的思想,累加左子树和右子树的组合数量
+ return dp[n] # 返回以1到n为节点的二叉搜索树的总数量
+
```
### Go
diff --git "a/problems/0115.\344\270\215\345\220\214\347\232\204\345\255\220\345\272\217\345\210\227.md" "b/problems/0115.\344\270\215\345\220\214\347\232\204\345\255\220\345\272\217\345\210\227.md"
index 6127f19045..8c82880d58 100644
--- "a/problems/0115.\344\270\215\345\220\214\347\232\204\345\255\220\345\272\217\345\210\227.md"
+++ "b/problems/0115.\344\270\215\345\220\214\347\232\204\345\255\220\345\272\217\345\210\227.md"
@@ -18,8 +18,9 @@
提示:
-0 <= s.length, t.length <= 1000
-s 和 t 由英文字母组成
+* 0 <= s.length, t.length <= 1000
+* s 和 t 由英文字母组成
+
## 思路
diff --git "a/problems/0123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.md" "b/problems/0123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.md"
index af6870d4cc..6ac9a576ea 100644
--- "a/problems/0123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.md"
+++ "b/problems/0123.\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272III.md"
@@ -242,9 +242,9 @@ class Solution {
for (int i = 1; i < len; i++) {
dp[i][1] = Math.max(dp[i - 1][1], -prices[i]);
- dp[i][2] = Math.max(dp[i - 1][2], dp[i][1] + prices[i]);
- dp[i][3] = Math.max(dp[i - 1][3], dp[i][2] - prices[i]);
- dp[i][4] = Math.max(dp[i - 1][4], dp[i][3] + prices[i]);
+ dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
+ dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
+ dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
return dp[len - 1][4];
diff --git "a/problems/0134.\345\212\240\346\262\271\347\253\231.md" "b/problems/0134.\345\212\240\346\262\271\347\253\231.md"
index f432bf0b1f..ad9acfbc80 100644
--- "a/problems/0134.\345\212\240\346\262\271\347\253\231.md"
+++ "b/problems/0134.\345\212\240\346\262\271\347\253\231.md"
@@ -249,44 +249,74 @@ class Solution {
```
### Python
+暴力法
+```python
+
+class Solution:
+ def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
+ for i in range(len(cost)):
+ rest = gas[i] - cost[i] # 记录剩余油量
+ index = (i + 1) % len(cost) # 下一个加油站的索引
+
+ while rest > 0 and index != i: # 模拟以i为起点行驶一圈(如果有rest==0,那么答案就不唯一了)
+ rest += gas[index] - cost[index] # 更新剩余油量
+ index = (index + 1) % len(cost) # 更新下一个加油站的索引
+
+ if rest >= 0 and index == i: # 如果以i为起点跑一圈,剩余油量>=0,并且回到起始位置
+ return i # 返回起始位置i
+
+ return -1 # 所有起始位置都无法环绕一圈,返回-1
+
+```
+贪心(版本一)
```python
-# 解法1
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
- n = len(gas)
- cur_sum = 0
- min_sum = float('inf')
+ curSum = 0 # 当前累计的剩余油量
+ minFuel = float('inf') # 从起点出发,油箱里的油量最小值
- for i in range(n):
- cur_sum += gas[i] - cost[i]
- min_sum = min(min_sum, cur_sum)
+ for i in range(len(gas)):
+ rest = gas[i] - cost[i]
+ curSum += rest
+ if curSum < minFuel:
+ minFuel = curSum
- if cur_sum < 0: return -1
- if min_sum >= 0: return 0
+ if curSum < 0:
+ return -1 # 情况1:整个行程的总消耗大于总供给,无法完成一圈
- for j in range(n - 1, 0, -1):
- min_sum += gas[j] - cost[j]
- if min_sum >= 0:
- return j
+ if minFuel >= 0:
+ return 0 # 情况2:从起点出发到任何一个加油站时油箱的剩余油量都不会小于0,可以从起点出发完成一圈
- return -1
-```
+ for i in range(len(gas) - 1, -1, -1):
+ rest = gas[i] - cost[i]
+ minFuel += rest
+ if minFuel >= 0:
+ return i # 情况3:找到一个位置使得从该位置出发油箱的剩余油量不会小于0,返回该位置的索引
+
+ return -1 # 无法完成一圈
+```
+贪心(版本二)
```python
-# 解法2
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
- start = 0
- curSum = 0
- totalSum = 0
+ curSum = 0 # 当前累计的剩余油量
+ totalSum = 0 # 总剩余油量
+ start = 0 # 起始位置
+
for i in range(len(gas)):
curSum += gas[i] - cost[i]
totalSum += gas[i] - cost[i]
- if curSum < 0:
- curSum = 0
- start = i + 1
- if totalSum < 0: return -1
+
+ if curSum < 0: # 当前累计剩余油量curSum小于0
+ start = i + 1 # 起始位置更新为i+1
+ curSum = 0 # curSum重新从0开始累计
+
+ if totalSum < 0:
+ return -1 # 总剩余油量totalSum小于0,说明无法环绕一圈
return start
+
+
```
### Go
diff --git "a/problems/0135.\345\210\206\345\217\221\347\263\226\346\236\234.md" "b/problems/0135.\345\210\206\345\217\221\347\263\226\346\236\234.md"
index 1ba1563fb3..cf3ccc8e90 100644
--- "a/problems/0135.\345\210\206\345\217\221\347\263\226\346\236\234.md"
+++ "b/problems/0135.\345\210\206\345\217\221\347\263\226\346\236\234.md"
@@ -178,13 +178,21 @@ class Solution {
class Solution:
def candy(self, ratings: List[int]) -> int:
candyVec = [1] * len(ratings)
+
+ # 从前向后遍历,处理右侧比左侧评分高的情况
for i in range(1, len(ratings)):
if ratings[i] > ratings[i - 1]:
candyVec[i] = candyVec[i - 1] + 1
- for j in range(len(ratings) - 2, -1, -1):
- if ratings[j] > ratings[j + 1]:
- candyVec[j] = max(candyVec[j], candyVec[j + 1] + 1)
- return sum(candyVec)
+
+ # 从后向前遍历,处理左侧比右侧评分高的情况
+ for i in range(len(ratings) - 2, -1, -1):
+ if ratings[i] > ratings[i + 1]:
+ candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1)
+
+ # 统计结果
+ result = sum(candyVec)
+ return result
+
```
### Go
diff --git "a/problems/0139.\345\215\225\350\257\215\346\213\206\345\210\206.md" "b/problems/0139.\345\215\225\350\257\215\346\213\206\345\210\206.md"
index 230942ef02..742fe06cb4 100644
--- "a/problems/0139.\345\215\225\350\257\215\346\213\206\345\210\206.md"
+++ "b/problems/0139.\345\215\225\350\257\215\346\213\206\345\210\206.md"
@@ -337,10 +337,53 @@ class Solution {
Python:
+回溯
+```python
+class Solution:
+ def backtracking(self, s: str, wordSet: set[str], startIndex: int) -> bool:
+ # 边界情况:已经遍历到字符串末尾,返回True
+ if startIndex >= len(s):
+ return True
+
+ # 遍历所有可能的拆分位置
+ for i in range(startIndex, len(s)):
+ word = s[startIndex:i + 1] # 截取子串
+ if word in wordSet and self.backtracking(s, wordSet, i + 1):
+ # 如果截取的子串在字典中,并且后续部分也可以被拆分成单词,返回True
+ return True
+
+ # 无法进行有效拆分,返回False
+ return False
+
+ def wordBreak(self, s: str, wordDict: List[str]) -> bool:
+ wordSet = set(wordDict) # 转换为哈希集合,提高查找效率
+ return self.backtracking(s, wordSet, 0)
+
+```
+DP(版本一)
+```python
+class Solution:
+ def wordBreak(self, s: str, wordDict: List[str]) -> bool:
+ wordSet = set(wordDict)
+ n = len(s)
+ dp = [False] * (n + 1) # dp[i] 表示字符串的前 i 个字符是否可以被拆分成单词
+ dp[0] = True # 初始状态,空字符串可以被拆分成单词
+
+ for i in range(1, n + 1): # 遍历背包
+ for j in range(i): # 遍历单词
+ if dp[j] and s[j:i] in wordSet:
+ dp[i] = True # 如果 s[0:j] 可以被拆分成单词,并且 s[j:i] 在单词集合中存在,则 s[0:i] 可以被拆分成单词
+ break
+
+ return dp[n]
+
+
+```
+DP(版本二)
+
```python
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
- '''排列'''
dp = [False]*(len(s) + 1)
dp[0] = True
# 遍历背包
@@ -351,17 +394,6 @@ class Solution:
dp[j] = dp[j] or (dp[j - len(word)] and word == s[j - len(word):j])
return dp[len(s)]
```
-```python
-class Solution: # 和视频中写法一致(和最上面C++写法一致)
- def wordBreak(self, s: str, wordDict: List[str]) -> bool:
- dp = [False]*(len(s)+1)
- dp[0]=True
- for j in range(1,len(s)+1):
- for i in range(j):
- word = s[i:j]
- if word in wordDict and dp[i]: dp[j]=True
- return dp[-1]
-```
diff --git "a/problems/0142.\347\216\257\345\275\242\351\223\276\350\241\250II.md" "b/problems/0142.\347\216\257\345\275\242\351\223\276\350\241\250II.md"
index e80a715a6c..f87d2cd914 100644
--- "a/problems/0142.\347\216\257\345\275\242\351\223\276\350\241\250II.md"
+++ "b/problems/0142.\347\216\257\345\275\242\351\223\276\350\241\250II.md"
@@ -437,6 +437,34 @@ object Solution {
}
```
+C#:
+```CSharp
+public class Solution
+{
+ public ListNode DetectCycle(ListNode head)
+ {
+ ListNode fast = head;
+ ListNode slow = head;
+ while (fast != null && fast.next != null)
+ {
+ slow = slow.next;
+ fast = fast.next.next;
+ if (fast == slow)
+ {
+ fast = head;
+ while (fast != slow)
+ {
+ fast = fast.next;
+ slow = slow.next;
+ }
+ return fast;
+ }
+ }
+ return null;
+ }
+}
+```
+
diff --git "a/problems/0198.\346\211\223\345\256\266\345\212\253\350\210\215.md" "b/problems/0198.\346\211\223\345\256\266\345\212\253\350\210\215.md"
index 6e682ec39e..bed7a4eabd 100644
--- "a/problems/0198.\346\211\223\345\256\266\345\212\253\350\210\215.md"
+++ "b/problems/0198.\346\211\223\345\256\266\345\212\253\350\210\215.md"
@@ -141,7 +141,36 @@ class Solution {
}
}
-// 空间优化 dp数组只存与计算相关的两次数据
+// 使用滚动数组思想,优化空间
+// 分析本题可以发现,所求结果仅依赖于前两种状态,此时可以使用滚动数组思想将空间复杂度降低为3个空间
+class Solution {
+ public int rob(int[] nums) {
+
+ int len = nums.length;
+
+ if (len == 0) return 0;
+ else if (len == 1) return nums[0];
+ else if (len == 2) return Math.max(nums[0],nums[1]);
+
+
+ int[] result = new int[3]; //存放选择的结果
+ result[0] = nums[0];
+ result[1] = Math.max(nums[0],nums[1]);
+
+
+ for(int i=2;i
diff --git "a/problems/0213.\346\211\223\345\256\266\345\212\253\350\210\215II.md" "b/problems/0213.\346\211\223\345\256\266\345\212\253\350\210\215II.md"
index 6395f3a884..3f532a410b 100644
--- "a/problems/0213.\346\211\223\345\256\266\345\212\253\350\210\215II.md"
+++ "b/problems/0213.\346\211\223\345\256\266\345\212\253\350\210\215II.md"
@@ -130,40 +130,93 @@ class Solution {
```
Python:
+
```Python
class Solution:
def rob(self, nums: List[int]) -> int:
- #在198入门级的打家劫舍问题上分两种情况考虑
- #一是不偷第一间房,二是不偷最后一间房
- if len(nums)==1:#题目中提示nums.length>=1,所以不需要考虑len(nums)==0的情况
+ if len(nums) == 0:
+ return 0
+ if len(nums) == 1:
return nums[0]
- val1=self.roblist(nums[1:])#不偷第一间房
- val2=self.roblist(nums[:-1])#不偷最后一间房
- return max(val1,val2)
-
- def roblist(self,nums):
- l=len(nums)
- dp=[0]*l
- dp[0]=nums[0]
- for i in range(1,l):
- if i==1:
- dp[i]=max(dp[i-1],nums[i])
- else:
- dp[i]=max(dp[i-1],dp[i-2]+nums[i])
- return dp[-1]
+
+ result1 = self.robRange(nums, 0, len(nums) - 2) # 情况二
+ result2 = self.robRange(nums, 1, len(nums) - 1) # 情况三
+ return max(result1, result2)
+ # 198.打家劫舍的逻辑
+ def robRange(self, nums: List[int], start: int, end: int) -> int:
+ if end == start:
+ return nums[start]
+
+ prev_max = nums[start]
+ curr_max = max(nums[start], nums[start + 1])
+
+ for i in range(start + 2, end + 1):
+ temp = curr_max
+ curr_max = max(prev_max + nums[i], curr_max)
+ prev_max = temp
+
+ return curr_max
+
```
+2维DP
```python
-class Solution: # 二维dp数组写法
+class Solution:
def rob(self, nums: List[int]) -> int:
- if len(nums)<3: return max(nums)
- return max(self.default(nums[:-1]),self.default(nums[1:]))
- def default(self,nums):
- dp = [[0,0] for _ in range(len(nums))]
+ if len(nums) < 3:
+ return max(nums)
+
+ # 情况二:不抢劫第一个房屋
+ result1 = self.robRange(nums[:-1])
+
+ # 情况三:不抢劫最后一个房屋
+ result2 = self.robRange(nums[1:])
+
+ return max(result1, result2)
+
+ def robRange(self, nums):
+ dp = [[0, 0] for _ in range(len(nums))]
dp[0][1] = nums[0]
- for i in range(1,len(nums)):
- dp[i][0] = max(dp[i-1])
- dp[i][1] = dp[i-1][0] + nums[i]
+
+ for i in range(1, len(nums)):
+ dp[i][0] = max(dp[i - 1])
+ dp[i][1] = dp[i - 1][0] + nums[i]
+
return max(dp[-1])
+
+
+
+```
+
+优化版
+```python
+class Solution:
+ def rob(self, nums: List[int]) -> int:
+ if not nums: # 如果没有房屋,返回0
+ return 0
+
+ if len(nums) == 1: # 如果只有一个房屋,返回该房屋的金额
+ return nums[0]
+
+ # 情况二:不抢劫第一个房屋
+ prev_max = 0 # 上一个房屋的最大金额
+ curr_max = 0 # 当前房屋的最大金额
+ for num in nums[1:]:
+ temp = curr_max # 临时变量保存当前房屋的最大金额
+ curr_max = max(prev_max + num, curr_max) # 更新当前房屋的最大金额
+ prev_max = temp # 更新上一个房屋的最大金额
+ result1 = curr_max
+
+ # 情况三:不抢劫最后一个房屋
+ prev_max = 0 # 上一个房屋的最大金额
+ curr_max = 0 # 当前房屋的最大金额
+ for num in nums[:-1]:
+ temp = curr_max # 临时变量保存当前房屋的最大金额
+ curr_max = max(prev_max + num, curr_max) # 更新当前房屋的最大金额
+ prev_max = temp # 更新上一个房屋的最大金额
+ result2 = curr_max
+
+ return max(result1, result2)
+
```
Go:
diff --git "a/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md" "b/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md"
index 41a1ede256..94c7940486 100644
--- "a/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md"
+++ "b/problems/0225.\347\224\250\351\230\237\345\210\227\345\256\236\347\216\260\346\240\210.md"
@@ -367,7 +367,7 @@ class MyStack {
```
优化,使用一个 Queue 实现,但用卡哥的逻辑实现
-```
+```Java
class MyStack {
Queue
diff --git "a/problems/0491.\351\200\222\345\242\236\345\255\220\345\272\217\345\210\227.md" "b/problems/0491.\351\200\222\345\242\236\345\255\220\345\272\217\345\210\227.md"
index 130b56667a..4b21008ea5 100644
--- "a/problems/0491.\351\200\222\345\242\236\345\255\220\345\272\217\345\210\227.md"
+++ "b/problems/0491.\351\200\222\345\242\236\345\255\220\345\272\217\345\210\227.md"
@@ -205,6 +205,30 @@ public:
### Java
+```Java
+//using set, aligned with the unimproved method
+class Solution {
+ List
diff --git "a/problems/0509.\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260.md" "b/problems/0509.\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260.md"
index 479b36a0f8..7ace072334 100644
--- "a/problems/0509.\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260.md"
+++ "b/problems/0509.\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260.md"
@@ -203,18 +203,9 @@ class Solution {
```
### Python
+动态规划(版本一)
```python
-class Solution:
- def fib(self, n: int) -> int:
- if n < 2:
- return n
- a, b, c = 0, 1, 0
- for i in range(1, n):
- c = a + b
- a, b = b, c
- return c
-# 动态规划 (注释版。无修饰)
class Solution:
def fib(self, n: int) -> int:
@@ -238,7 +229,48 @@ class Solution:
# 返回答案
return dp[n]
-# 递归实现
+```
+动态规划(版本二)
+```python
+
+class Solution:
+ def fib(self, n: int) -> int:
+ if n <= 1:
+ return n
+
+ dp = [0, 1]
+
+ for i in range(2, n + 1):
+ total = dp[0] + dp[1]
+ dp[0] = dp[1]
+ dp[1] = total
+
+ return dp[1]
+
+
+```
+动态规划(版本三)
+```python
+class Solution:
+ def fib(self, n: int) -> int:
+ if n <= 1:
+ return n
+
+ prev1, prev2 = 0, 1
+
+ for _ in range(2, n + 1):
+ curr = prev1 + prev2
+ prev1, prev2 = prev2, curr
+
+ return prev2
+
+
+
+
+```
+递归(版本一)
+```python
+
class Solution:
def fib(self, n: int) -> int:
if n < 2:
diff --git "a/problems/0518.\351\233\266\351\222\261\345\205\221\346\215\242II.md" "b/problems/0518.\351\233\266\351\222\261\345\205\221\346\215\242II.md"
index c208754f77..8da351148b 100644
--- "a/problems/0518.\351\233\266\351\222\261\345\205\221\346\215\242II.md"
+++ "b/problems/0518.\351\233\266\351\222\261\345\205\221\346\215\242II.md"
@@ -282,17 +282,18 @@ func change(amount int, coins []int) int {
Rust:
```rust
-pub fn change(amount: i32, coins: Vec
diff --git "a/problems/1005.K\346\254\241\345\217\226\345\217\215\345\220\216\346\234\200\345\244\247\345\214\226\347\232\204\346\225\260\347\273\204\345\222\214.md" "b/problems/1005.K\346\254\241\345\217\226\345\217\215\345\220\216\346\234\200\345\244\247\345\214\226\347\232\204\346\225\260\347\273\204\345\222\214.md"
index 571bc2ac51..b06d8b2e9f 100644
--- "a/problems/1005.K\346\254\241\345\217\226\345\217\215\345\220\216\346\234\200\345\244\247\345\214\226\347\232\204\346\225\260\347\273\204\345\222\214.md"
+++ "b/problems/1005.K\346\254\241\345\217\226\345\217\215\345\220\216\346\234\200\345\244\247\345\214\226\347\232\204\346\225\260\347\273\204\345\222\214.md"
@@ -131,17 +131,23 @@ class Solution {
```
### Python
+贪心
```python
class Solution:
def largestSumAfterKNegations(self, A: List[int], K: int) -> int:
- A = sorted(A, key=abs, reverse=True) # 将A按绝对值从大到小排列
- for i in range(len(A)):
- if K > 0 and A[i] < 0:
+ A.sort(key=lambda x: abs(x), reverse=True) # 第一步:按照绝对值降序排序数组A
+
+ for i in range(len(A)): # 第二步:执行K次取反操作
+ if A[i] < 0 and K > 0:
A[i] *= -1
K -= 1
- if K > 0:
- A[-1] *= (-1)**K #取A最后一个数只需要写-1
- return sum(A)
+
+ if K % 2 == 1: # 第三步:如果K还有剩余次数,将绝对值最小的元素取反
+ A[-1] *= -1
+
+ result = sum(A) # 第四步:计算数组A的元素和
+ return result
+
```
### Go
diff --git "a/problems/1035.\344\270\215\347\233\270\344\272\244\347\232\204\347\272\277.md" "b/problems/1035.\344\270\215\347\233\270\344\272\244\347\232\204\347\272\277.md"
index 7b60abdda3..7142d75c09 100644
--- "a/problems/1035.\344\270\215\347\233\270\344\272\244\347\232\204\347\272\277.md"
+++ "b/problems/1035.\344\270\215\347\233\270\344\272\244\347\232\204\347\272\277.md"
@@ -17,6 +17,11 @@
![1035.不相交的线](https://code-thinking-1253855093.file.myqcloud.com/pics/2021032116363533.png)
+## 算法公开课
+
+**《代码随想录》算法视频公开课:[动态规划之子序列问题,换汤不换药 | LeetCode:1035.不相交的线](https://www.bilibili.com/video/BV1h84y1x7MP),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
+
+
## 思路
相信不少录友看到这道题目都没啥思路,我们来逐步分析一下。
diff --git "a/problems/1049.\346\234\200\345\220\216\344\270\200\345\235\227\347\237\263\345\244\264\347\232\204\351\207\215\351\207\217II.md" "b/problems/1049.\346\234\200\345\220\216\344\270\200\345\235\227\347\237\263\345\244\264\347\232\204\351\207\215\351\207\217II.md"
index 210ce73738..a978b80262 100644
--- "a/problems/1049.\346\234\200\345\220\216\344\270\200\345\235\227\347\237\263\345\244\264\347\232\204\351\207\215\351\207\217II.md"
+++ "b/problems/1049.\346\234\200\345\220\216\344\270\200\345\235\227\347\237\263\345\244\264\347\232\204\351\207\215\351\207\217II.md"
@@ -224,18 +224,79 @@ class Solution {
```
### Python:
+卡哥版
```python
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
- sumweight = sum(stones)
- target = sumweight // 2
- dp = [0] * (target + 1)
- for i in range(len(stones)):
- for j in range(target, stones[i] - 1, -1):
- dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
- return sumweight - 2 * dp[target]
+ dp = [0] * 15001
+ total_sum = sum(stones)
+ target = total_sum // 2
+
+ for stone in stones: # 遍历物品
+ for j in range(target, stone - 1, -1): # 遍历背包
+ dp[j] = max(dp[j], dp[j - stone] + stone)
+
+ return total_sum - dp[target] - dp[target]
+
+```
+二维DP版
+```python
+class Solution:
+ def lastStoneWeightII(self, stones: List[int]) -> int:
+ total_sum = sum(stones)
+ target = total_sum // 2
+
+ # 创建二维dp数组,行数为石头的数量加1,列数为target加1
+ # dp[i][j]表示前i个石头能否组成总重量为j
+ dp = [[False] * (target + 1) for _ in range(len(stones) + 1)]
+
+ # 初始化第一列,表示总重量为0时,前i个石头都能组成
+ for i in range(len(stones) + 1):
+ dp[i][0] = True
+
+ for i in range(1, len(stones) + 1):
+ for j in range(1, target + 1):
+ # 如果当前石头重量大于当前目标重量j,则无法选择该石头
+ if stones[i - 1] > j:
+ dp[i][j] = dp[i - 1][j]
+ else:
+ # 可选择该石头或不选择该石头
+ dp[i][j] = dp[i - 1][j] or dp[i - 1][j - stones[i - 1]]
+
+ # 找到最大的重量i,使得dp[len(stones)][i]为True
+ # 返回总重量减去两倍的最接近总重量一半的重量
+ for i in range(target, -1, -1):
+ if dp[len(stones)][i]:
+ return total_sum - 2 * i
+
+ return 0
+
+
```
+一维DP版
+```python
+class Solution:
+ def lastStoneWeightII(self, stones):
+ total_sum = sum(stones)
+ target = total_sum // 2
+ dp = [False] * (target + 1)
+ dp[0] = True
+
+ for stone in stones:
+ for j in range(target, stone - 1, -1):
+ # 判断当前重量是否可以通过选择之前的石头得到或选择当前石头和之前的石头得到
+ dp[j] = dp[j] or dp[j - stone]
+ for i in range(target, -1, -1):
+ if dp[i]:
+ # 返回剩余石头的重量,即总重量减去两倍的最接近总重量一半的重量
+ return total_sum - 2 * i
+
+ return 0
+
+
+
+```
### Go:
```go
func lastStoneWeightII(stones []int) int {
@@ -379,8 +440,23 @@ object Solution {
}
```
-
-
+### Rust
+
+```rust
+impl Solution {
+ pub fn last_stone_weight_ii(stones: Vec 参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!> result = new ArrayList<>();
+ List
> findSubsequences(int[] nums) {
+ backTracking(nums, 0);
+ return result;
+ }
+ private void backTracking(int[] nums, int startIndex){
+ if(path.size() >= 2)
+ result.add(new ArrayList<>(path));
+ HashSet