This commit is contained in:
programmercarl
2023-09-19 16:21:37 +08:00
parent ab4c44d2a3
commit 631b333c08
9 changed files with 17 additions and 34 deletions

View File

@ -39,8 +39,8 @@
本文深度讲解如下三种方法:
* 双指针
* 动态规划
* 暴力解
* 双指针优化
* 单调栈
### 暴力解法

View File

@ -35,13 +35,13 @@
但思路是相似的,还是要看最大覆盖范围。
本题要计算最步数,那么就要想清楚什么时候步数才一定要加一呢?
本题要计算最步数,那么就要想清楚什么时候步数才一定要加一呢?
贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最步数。
贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最步数。
思路虽然是这样,但在写代码的时候还不能真的能跳多远就跳多远,那样就不知道下一步最远能跳到哪里了。
**所以真正解题的时候,要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最步数!**
**所以真正解题的时候,要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最步数!**
**这里需要统计两个覆盖范围,当前这一步的最大覆盖和下一步最大覆盖**
@ -144,7 +144,7 @@ public:
但代码又十分简单,贪心就是这么巧妙。
理解本题的关键在于:**以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点**,这个范围内最步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位。
理解本题的关键在于:**以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点**,这个范围内最步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位。
## 其他语言版本
@ -276,9 +276,9 @@ class Solution:
for i in range(len(nums)): # 遍历数组
for j in range(nums[i] + 1): # 在当前位置能够跳跃的范围内遍历
if i + j < len(nums): # 确保下一跳的位置不超过数组范围
result[i + j] = min(result[i + j], result[i] + 1) # 更新到达下一跳位置的最步数
result[i + j] = min(result[i + j], result[i] + 1) # 更新到达下一跳位置的最步数
return result[-1] # 返回到达最后一个位置的最步数
return result[-1] # 返回到达最后一个位置的最步数
```

View File

@ -209,11 +209,11 @@ private:
vector<int> path; // 符合条件的结果
void backtracking(int targetSum, int k, int sum, int startIndex) {
if (sum > targetSum) { // 剪枝操作
return; // 如果path.size() == k 但sum != targetSum 直接返回
return;
}
if (path.size() == k) {
if (sum == targetSum) result.push_back(path);
return;
return; // 如果path.size() == k 但sum != targetSum 直接返回
}
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 剪枝
sum += i; // 处理

View File

@ -240,9 +240,9 @@ class Solution {
// 因为马上dp[0]和dp[2]的数据都会变
int temp = dp[0];
int temp1 = dp[2];
dp[0] = Math.max(dp[0], Math.max(dp[3], dp[1]) - prices[i-1]);
dp[0] = Math.max(dp[0], Math.max(dp[3], dp[1]) - prices[i]);
dp[1] = Math.max(dp[1], dp[3]);
dp[2] = temp + prices[i-1];
dp[2] = temp + prices[i];
dp[3] = temp1;
}
return Math.max(dp[3],Math.max(dp[1],dp[2]));

View File

@ -261,7 +261,7 @@ public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
TreeNode* pre = NULL; // 记录前一个节点
pre = NULL; // 记录前一个节点
result.clear();
searchBST(root);

View File

@ -330,23 +330,6 @@ class Solution:
return root
```
递归法(版本二)精简
```python
class Solution:
def trimBST(self, root: TreeNode, low: int, high: int) -> TreeNode:
if root is None:
return None
if root.val < low:
return self.trimBST(root.right, low, high)
if root.val > high:
return self.trimBST(root.left, low, high)
root.left = self.trimBST(root.left, low, high)
root.right = self.trimBST(root.right, low, high)
return root
```
迭代法
```python
class Solution:

View File

@ -66,7 +66,7 @@ if (s[i - 1] == t[j - 1]) {
## 两个字符串的删除操作
[动态规划583.两个字符串的删除操作](https://programmercarl.com/0583.两个字符串的删除操作.html)给定两个单词 word1 和 word2找到使得 word1 和 word2 相同所需的最步数,每步可以删除任意一个字符串中的一个字符。
[动态规划583.两个字符串的删除操作](https://programmercarl.com/0583.两个字符串的删除操作.html)给定两个单词 word1 和 word2找到使得 word1 和 word2 相同所需的最步数,每步可以删除任意一个字符串中的一个字符。
本题和[动态规划115.不同的子序列](https://programmercarl.com/0115.不同的子序列.html)相比,其实就是两个字符串可以都可以删除了,情况虽说复杂一些,但整体思路是不变的。

View File

@ -21,11 +21,11 @@
使用VIM的话本地服务器开发机一刀流无缝切换爽不。
IDE那么很吃内存打开个IDE卡半天用VIM就很轻便了秒开有木有
IDE那么很吃内存打开个IDE卡半天用VIM就很轻便了秒开
而且在我们日常开发中工作年头多了都会发现没有纯粹的C++Java开发啥的就是 C++也得写Java也得写有时候写Go起个http服务写Python处理一下数据写shell搞个自动部署编译啥的。 **总是就是啥语言就得写,一些以项目需求为导向!**
写语言还要切换不同的IDE熟悉不同的操作姿势,想想是不是很麻烦。
写语言还要切换不同的IDE熟悉不同的操作规则,想想是不是很麻烦。
听说好像现在有的IDE可以支持很多语言了这个我还不太了解但能确定的是IDE支持的语言再多也不会有vim多。

View File

@ -289,7 +289,7 @@ join(6, 2);
此时我们生成的的有向图为:
![](https://cdn.tftree.top/others/jion.jpg)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230910203210.png)
有录友可能想,`join(3, 8)` 在图中为什么 将 元素1 连向元素 3 而不是将 元素 8 连向 元素 3 呢?