mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-07 15:45:40 +08:00
Merge branch 'master' into patch-6
This commit is contained in:
@ -168,7 +168,8 @@ class Solution:
|
|||||||
Do not return anything, modify nums in-place instead.
|
Do not return anything, modify nums in-place instead.
|
||||||
"""
|
"""
|
||||||
length = len(nums)
|
length = len(nums)
|
||||||
for i in range(length - 1, -1, -1):
|
for i in range(length - 2, -1, -1): # 从倒数第二个开始
|
||||||
|
if nums[i]>=nums[i+1]: continue # 剪枝去重
|
||||||
for j in range(length - 1, i, -1):
|
for j in range(length - 1, i, -1):
|
||||||
if nums[j] > nums[i]:
|
if nums[j] > nums[i]:
|
||||||
nums[j], nums[i] = nums[i], nums[j]
|
nums[j], nums[i] = nums[i], nums[j]
|
||||||
|
@ -355,8 +355,8 @@ class Solution:
|
|||||||
while left <= right:
|
while left <= right:
|
||||||
middle = left + (right-left) // 2
|
middle = left + (right-left) // 2
|
||||||
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
|
if nums[middle] >= target: # 寻找左边界,nums[middle] == target的时候更新right
|
||||||
right = middle - 1;
|
right = middle - 1
|
||||||
leftBoder = right;
|
leftBoder = right
|
||||||
else:
|
else:
|
||||||
left = middle + 1
|
left = middle + 1
|
||||||
return leftBoder
|
return leftBoder
|
||||||
|
@ -471,7 +471,7 @@ class Solution {
|
|||||||
### Python:
|
### Python:
|
||||||
|
|
||||||
双指针法
|
双指针法
|
||||||
```python3
|
```Python
|
||||||
class Solution:
|
class Solution:
|
||||||
def trap(self, height: List[int]) -> int:
|
def trap(self, height: List[int]) -> int:
|
||||||
res = 0
|
res = 0
|
||||||
@ -510,7 +510,7 @@ class Solution:
|
|||||||
return result
|
return result
|
||||||
```
|
```
|
||||||
单调栈
|
单调栈
|
||||||
```python3
|
```Python
|
||||||
class Solution:
|
class Solution:
|
||||||
def trap(self, height: List[int]) -> int:
|
def trap(self, height: List[int]) -> int:
|
||||||
# 单调栈
|
# 单调栈
|
||||||
|
@ -73,11 +73,11 @@ public:
|
|||||||
for (int i = 0; i < nums.size(); i++) {
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖最远距离下标
|
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖最远距离下标
|
||||||
if (i == curDistance) { // 遇到当前覆盖最远距离下标
|
if (i == curDistance) { // 遇到当前覆盖最远距离下标
|
||||||
if (curDistance != nums.size() - 1) { // 如果当前覆盖最远距离下标不是终点
|
if (curDistance < nums.size() - 1) { // 如果当前覆盖最远距离下标不是终点
|
||||||
ans++; // 需要走下一步
|
ans++; // 需要走下一步
|
||||||
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
|
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
|
||||||
if (nextDistance >= nums.size() - 1) break; // 下一步的覆盖范围已经可以达到终点,结束循环
|
if (nextDistance >= nums.size() - 1) break; // 下一步的覆盖范围已经可以达到终点,结束循环
|
||||||
} else break; // 当前覆盖最远距离下标是集合终点,不用做ans++操作了,直接结束
|
} else break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
@ -126,7 +126,7 @@ public:
|
|||||||
|
|
||||||
可以看出版本二的代码相对于版本一简化了不少!
|
可以看出版本二的代码相对于版本一简化了不少!
|
||||||
|
|
||||||
其精髓在于控制移动下标i只移动到nums.size() - 2的位置,所以移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不用考虑别的了。
|
**其精髓在于控制移动下标i只移动到nums.size() - 2的位置**,所以移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不用考虑别的了。
|
||||||
|
|
||||||
## 总结
|
## 总结
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
|
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
|
||||||
|
|
||||||
示例:
|
示例:
|
||||||
输入: [-2,1,-3,4,-1,2,1,-5,4]
|
* 输入: [-2,1,-3,4,-1,2,1,-5,4]
|
||||||
输出: 6
|
* 输出: 6
|
||||||
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
|
* 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
|
||||||
|
|
||||||
|
|
||||||
## 暴力解法
|
## 暴力解法
|
||||||
@ -103,8 +103,28 @@ public:
|
|||||||
|
|
||||||
当然题目没有说如果数组为空,应该返回什么,所以数组为空的话返回啥都可以了。
|
当然题目没有说如果数组为空,应该返回什么,所以数组为空的话返回啥都可以了。
|
||||||
|
|
||||||
|
|
||||||
|
## 常见误区
|
||||||
|
|
||||||
|
误区一:
|
||||||
|
|
||||||
不少同学认为 如果输入用例都是-1,或者 都是负数,这个贪心算法跑出来的结果是0, 这是**又一次证明脑洞模拟不靠谱的经典案例**,建议大家把代码运行一下试一试,就知道了,也会理解 为什么 result 要初始化为最小负数了。
|
不少同学认为 如果输入用例都是-1,或者 都是负数,这个贪心算法跑出来的结果是0, 这是**又一次证明脑洞模拟不靠谱的经典案例**,建议大家把代码运行一下试一试,就知道了,也会理解 为什么 result 要初始化为最小负数了。
|
||||||
|
|
||||||
|
|
||||||
|
误区二:
|
||||||
|
|
||||||
|
大家在使用贪心算法求解本题,经常陷入的误区,就是分不清,是遇到 负数就选择起始位置,还是连续和为负选择起始位置。
|
||||||
|
|
||||||
|
在动画演示用,大家可以发现, 4,遇到 -1 的时候,我们依然累加了,为什么呢?
|
||||||
|
|
||||||
|
因为和为3,只要连续和还是正数就会 对后面的元素 起到增大总和的作用。 所以只要连续和为正数我们就保留。
|
||||||
|
|
||||||
|
这里也会有录友疑惑,那 4 + -1 之后 不就变小了吗? 会不会错过 4 成为最大连续和的可能性?
|
||||||
|
|
||||||
|
其实并不会,因为还有一个变量result 一直在更新 最大的连续和,只要有更大的连续和出现,result就更新了,那么result已经把4更新了,后面 连续和变成3,也不会对最后结果有影响。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 动态规划
|
## 动态规划
|
||||||
|
|
||||||
当然本题还可以用动态规划来做,当前[「代码随想录」](https://img-blog.csdnimg.cn/20201124161234338.png)主要讲解贪心系列,后续到动态规划系列的时候会详细讲解本题的dp方法。
|
当然本题还可以用动态规划来做,当前[「代码随想录」](https://img-blog.csdnimg.cn/20201124161234338.png)主要讲解贪心系列,后续到动态规划系列的时候会详细讲解本题的dp方法。
|
||||||
@ -135,7 +155,7 @@ public:
|
|||||||
|
|
||||||
本题的贪心思路其实并不好想,这也进一步验证了,别看贪心理论很直白,有时候看似是常识,但贪心的题目一点都不简单!
|
本题的贪心思路其实并不好想,这也进一步验证了,别看贪心理论很直白,有时候看似是常识,但贪心的题目一点都不简单!
|
||||||
|
|
||||||
后续将介绍的贪心题目都挺难的,哈哈,所以贪心很有意思,别小看贪心!
|
后续将介绍的贪心题目都挺难的,所以贪心很有意思,别小看贪心!
|
||||||
|
|
||||||
## 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
一些同学可能感觉,我在讲贪心系列的时候,题目和题目之间貌似没有什么联系?
|
一些同学可能感觉,我在讲贪心系列的时候,题目和题目之间貌似没有什么联系?
|
||||||
|
|
||||||
**是真的就是没什么联系,因为贪心无套路!**没有个整体的贪心框架解决一系列问题,只能是接触各种类型的题目锻炼自己的贪心思维!
|
**是真的就是没什么联系,因为贪心无套路**!没有个整体的贪心框架解决一系列问题,只能是接触各种类型的题目锻炼自己的贪心思维!
|
||||||
|
|
||||||
## 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
|
@ -40,6 +40,9 @@
|
|||||||
* 0 <= s.length <= 3000
|
* 0 <= s.length <= 3000
|
||||||
* s 仅由数字组成
|
* s 仅由数字组成
|
||||||
|
|
||||||
|
# 算法公开课
|
||||||
|
|
||||||
|
**《代码随想录》算法视频公开课:[93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
|
||||||
|
|
||||||
# 思路
|
# 思路
|
||||||
|
|
||||||
@ -424,6 +427,30 @@ class Solution:
|
|||||||
return True
|
return True
|
||||||
```
|
```
|
||||||
|
|
||||||
|
python3; 简单拼接版本(类似Leetcode131写法):
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def restoreIpAddresses(self, s: str) -> List[str]:
|
||||||
|
global results, path
|
||||||
|
results = []
|
||||||
|
path = []
|
||||||
|
self.backtracking(s,0)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def backtracking(self,s,index):
|
||||||
|
global results,path
|
||||||
|
if index == len(s) and len(path)==4:
|
||||||
|
results.append('.'.join(path)) # 在连接时需要中间间隔符号的话就在''中间写上对应的间隔符
|
||||||
|
return
|
||||||
|
for i in range(index,len(s)):
|
||||||
|
if len(path)>3: break # 剪枝
|
||||||
|
temp = s[index:i+1]
|
||||||
|
if (int(temp)<256 and int(temp)>0 and temp[0]!='0') or (temp=='0'):
|
||||||
|
path.append(temp)
|
||||||
|
self.backtracking(s,i+1)
|
||||||
|
path.pop()
|
||||||
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -23,10 +23,12 @@
|
|||||||
* 111.二叉树的最小深度
|
* 111.二叉树的最小深度
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 102.二叉树的层序遍历
|
# 102.二叉树的层序遍历
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
|
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
|
||||||
|
@ -397,6 +397,9 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Python
|
||||||
|
|
||||||
|
|
||||||
# 105.从前序与中序遍历序列构造二叉树
|
# 105.从前序与中序遍历序列构造二叉树
|
||||||
|
|
||||||
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||||||
@ -650,6 +653,37 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Python
|
## Python
|
||||||
|
```python
|
||||||
|
class Solution:
|
||||||
|
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
|
||||||
|
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
|
||||||
|
if not postorder:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 第二步: 后序遍历的最后一个就是当前的中间节点
|
||||||
|
root_val = postorder[-1]
|
||||||
|
root = TreeNode(root_val)
|
||||||
|
|
||||||
|
# 第三步: 找切割点.
|
||||||
|
root_index = inorder.index(root_val)
|
||||||
|
|
||||||
|
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
|
||||||
|
left_inorder = inorder[:root_index]
|
||||||
|
right_inorder = inorder[root_index + 1:]
|
||||||
|
|
||||||
|
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
|
||||||
|
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
|
||||||
|
left_postorder = postorder[:len(left_inorder)]
|
||||||
|
right_postorder = postorder[len(left_inorder): len(postorder) - 1]
|
||||||
|
|
||||||
|
|
||||||
|
# 第六步: 递归
|
||||||
|
root.left = self.buildTree(left_inorder, left_postorder)
|
||||||
|
root.right = self.buildTree(right_inorder, right_postorder)
|
||||||
|
|
||||||
|
# 第七步: 返回答案
|
||||||
|
return root
|
||||||
|
```
|
||||||
|
|
||||||
105.从前序与中序遍历序列构造二叉树
|
105.从前序与中序遍历序列构造二叉树
|
||||||
|
|
||||||
|
@ -155,14 +155,14 @@ public:
|
|||||||
以上代码精简之后如下:
|
以上代码精简之后如下:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
class solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
bool hasPathSum(TreeNode* root, int sum) {
|
bool hasPathSum(TreeNode* root, int sum) {
|
||||||
if (root == null) return false;
|
if (!root) return false;
|
||||||
if (!root->left && !root->right && sum == root->val) {
|
if (!root->left && !root->right && sum == root->val) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
|
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@ -83,6 +83,7 @@ public:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## 其他语言版本
|
## 其他语言版本
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
|
@ -88,7 +88,7 @@ public:
|
|||||||
* 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
|
* 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
|
||||||
* 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
|
* 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
|
||||||
|
|
||||||
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能这个负数填平,能把这个负数填平的节点就是出发节点。
|
* 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。
|
||||||
|
|
||||||
C++代码如下:
|
C++代码如下:
|
||||||
|
|
||||||
|
@ -442,7 +442,7 @@ class Solution:
|
|||||||
while left <= right and s[left] == ' ': #去除开头的空格
|
while left <= right and s[left] == ' ': #去除开头的空格
|
||||||
left += 1
|
left += 1
|
||||||
while left <= right and s[right] == ' ': #去除结尾的空格
|
while left <= right and s[right] == ' ': #去除结尾的空格
|
||||||
right = right-1
|
right -= 1
|
||||||
tmp = []
|
tmp = []
|
||||||
while left <= right: #去除单词中间多余的空格
|
while left <= right: #去除单词中间多余的空格
|
||||||
if s[left] != ' ':
|
if s[left] != ' ':
|
||||||
|
@ -628,6 +628,43 @@ impl Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
C#:
|
||||||
|
三指针法, 感觉会更直观:
|
||||||
|
|
||||||
|
```cs
|
||||||
|
public LinkNumbers Reverse()
|
||||||
|
{
|
||||||
|
///用三指针,写的过程中能够弥补二指针在翻转过程中的想象
|
||||||
|
LinkNumbers pre = null;
|
||||||
|
var move = root;
|
||||||
|
var next = root;
|
||||||
|
|
||||||
|
while (next != null)
|
||||||
|
{
|
||||||
|
next = next.linknext;
|
||||||
|
move.linknext = pre;
|
||||||
|
pre = move;
|
||||||
|
move = next;
|
||||||
|
}
|
||||||
|
root = pre;
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
///LinkNumbers的定义
|
||||||
|
public class LinkNumbers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 链表值
|
||||||
|
/// </summary>
|
||||||
|
public int value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 链表指针
|
||||||
|
/// </summary>
|
||||||
|
public LinkNumbers linknext { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
|
@ -38,7 +38,7 @@ queue.empty(); // 返回 false
|
|||||||
|
|
||||||
## 思路
|
## 思路
|
||||||
|
|
||||||
《代码随想录》算法公开课:[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对链表的理解。
|
《代码随想录》算法公开课:[栈的基本操作! | LeetCode:232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对栈和队列的理解。
|
||||||
|
|
||||||
|
|
||||||
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
|
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
|
||||||
@ -662,3 +662,4 @@ impl MyQueue {
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -468,7 +468,7 @@ class Solution {
|
|||||||
---
|
---
|
||||||
## Python:
|
## Python:
|
||||||
递归法+隐形回溯
|
递归法+隐形回溯
|
||||||
```Python3
|
```Python
|
||||||
# Definition for a binary tree node.
|
# Definition for a binary tree node.
|
||||||
# class TreeNode:
|
# class TreeNode:
|
||||||
# def __init__(self, val=0, left=None, right=None):
|
# def __init__(self, val=0, left=None, right=None):
|
||||||
@ -499,7 +499,7 @@ class Solution:
|
|||||||
|
|
||||||
迭代法:
|
迭代法:
|
||||||
|
|
||||||
```python3
|
```Python
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,8 +137,19 @@ class Solution {
|
|||||||
resSet.add(i);
|
resSet.add(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//将结果集合转为数组
|
|
||||||
|
//方法1:将结果集合转为数组
|
||||||
|
|
||||||
return resSet.stream().mapToInt(x -> x).toArray();
|
return resSet.stream().mapToInt(x -> x).toArray();
|
||||||
|
|
||||||
|
//方法2:另外申请一个数组存放setRes中的元素,最后返回数组
|
||||||
|
int[] arr = new int[setRes.size()];
|
||||||
|
int j = 0;
|
||||||
|
for(int i : setRes){
|
||||||
|
arr[j++] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -423,3 +434,4 @@ C#:
|
|||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
C++代码整体如下:
|
C++代码整体如下:
|
||||||
|
|
||||||
```CPP
|
```CPP
|
||||||
|
// 版本一
|
||||||
// 时间复杂度:O(nlogn)
|
// 时间复杂度:O(nlogn)
|
||||||
// 空间复杂度:O(1)
|
// 空间复杂度:O(1)
|
||||||
class Solution {
|
class Solution {
|
||||||
@ -61,8 +62,8 @@ public:
|
|||||||
sort(s.begin(), s.end());
|
sort(s.begin(), s.end());
|
||||||
int index = s.size() - 1; // 饼干数组的下标
|
int index = s.size() - 1; // 饼干数组的下标
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = g.size() - 1; i >= 0; i--) {
|
for (int i = g.size() - 1; i >= 0; i--) { // 遍历胃口
|
||||||
if (index >= 0 && s[index] >= g[i]) {
|
if (index >= 0 && s[index] >= g[i]) { // 遍历饼干
|
||||||
result++;
|
result++;
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
@ -76,6 +77,26 @@ public:
|
|||||||
|
|
||||||
有的同学看到要遍历两个数组,就想到用两个for循环,那样逻辑其实就复杂了。
|
有的同学看到要遍历两个数组,就想到用两个for循环,那样逻辑其实就复杂了。
|
||||||
|
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
|
||||||
|
注意版本一的代码中,可以看出来,是先遍历的胃口,在遍历的饼干,那么可不可以 先遍历 饼干,在遍历胃口呢?
|
||||||
|
|
||||||
|
其实是不可以的。
|
||||||
|
|
||||||
|
外面的for 是里的下标i 是固定移动的,而if里面的下标 index 是符合条件才移动的。
|
||||||
|
|
||||||
|
如果 for 控制的是饼干, if 控制胃口,就是出现如下情况 :
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
if 里的 index 指向 胃口 10, for里的i指向饼干9,因为 饼干9 满足不了 胃口10,所以 i 持续向前移动,而index 走不到` s[index] >= g[i]` 的逻辑,所以index不会移动,那么当i 持续向前移动,最后所有的饼干都匹配不上。
|
||||||
|
|
||||||
|
所以 一定要for 控制 胃口,里面的if控制饼干。
|
||||||
|
|
||||||
|
|
||||||
|
### 其他思路
|
||||||
|
|
||||||
**也可以换一个思路,小饼干先喂饱小胃口**
|
**也可以换一个思路,小饼干先喂饱小胃口**
|
||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
@ -87,8 +108,8 @@ public:
|
|||||||
sort(g.begin(),g.end());
|
sort(g.begin(),g.end());
|
||||||
sort(s.begin(),s.end());
|
sort(s.begin(),s.end());
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int i = 0;i < s.size();++i){
|
for(int i = 0; i < s.size(); i++) { // 饼干
|
||||||
if(index < g.size() && g[index] <= s[i]){
|
if(index < g.size() && g[index] <= s[i]){ // 胃口
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,6 +118,10 @@ public:
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
细心的录友可以发现,这种写法,两个循环的顺序改变了,先遍历的饼干,在遍历的胃口,这是因为遍历顺序变了,我们是从小到大遍历。
|
||||||
|
|
||||||
|
理由在上面 “注意事项”中 已经讲过。
|
||||||
|
|
||||||
## 总结
|
## 总结
|
||||||
|
|
||||||
这道题是贪心很好的一道入门题目,思路还是比较容易想到的。
|
这道题是贪心很好的一道入门题目,思路还是比较容易想到的。
|
||||||
@ -148,7 +173,7 @@ class Solution {
|
|||||||
### Python
|
### Python
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
# 思路1:优先考虑胃饼干
|
# 思路1:优先考虑小胃口
|
||||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||||
g.sort()
|
g.sort()
|
||||||
s.sort()
|
s.sort()
|
||||||
@ -160,7 +185,7 @@ class Solution:
|
|||||||
```
|
```
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
# 思路2:优先考虑胃口
|
# 思路2:优先考虑大胃口
|
||||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||||
g.sort()
|
g.sort()
|
||||||
s.sort()
|
s.sort()
|
||||||
|
@ -209,29 +209,28 @@ class Solution {
|
|||||||
# self.right = right
|
# self.right = right
|
||||||
class Solution:
|
class Solution:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pre = TreeNode()
|
self.count = 0
|
||||||
|
|
||||||
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
|
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
|
||||||
|
if root == None:
|
||||||
|
return
|
||||||
'''
|
'''
|
||||||
倒序累加替换:
|
倒序累加替换:
|
||||||
[2, 5, 13] -> [[2]+[1]+[0], [2]+[1], [2]] -> [20, 18, 13]
|
|
||||||
'''
|
'''
|
||||||
self.traversal(root)
|
# 右
|
||||||
|
self.convertBST(root.right)
|
||||||
|
|
||||||
|
# 中
|
||||||
|
# 中节点:用当前root的值加上pre的值
|
||||||
|
self.count += root.val
|
||||||
|
|
||||||
|
root.val = self.count
|
||||||
|
|
||||||
|
# 左
|
||||||
|
self.convertBST(root.left)
|
||||||
|
|
||||||
return root
|
return root
|
||||||
|
|
||||||
def traversal(self, root: TreeNode) -> None:
|
|
||||||
# 因为要遍历整棵树,所以递归函数不需要返回值
|
|
||||||
# Base Case
|
|
||||||
if not root:
|
|
||||||
return None
|
|
||||||
# 单层递归逻辑:中序遍历的反译 - 右中左
|
|
||||||
self.traversal(root.right) # 右
|
|
||||||
|
|
||||||
# 中节点:用当前root的值加上pre的值
|
|
||||||
root.val += self.pre.val # 中
|
|
||||||
self.pre = root
|
|
||||||
|
|
||||||
self.traversal(root.left) # 左
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。
|
那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。
|
||||||
|
|
||||||
那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了),全局最优:整个 数组和 达到最大。
|
那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值和可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了),全局最优:整个 数组和 达到最大。
|
||||||
|
|
||||||
虽然这道题目大家做的时候,可能都不会去想什么贪心算法,一鼓作气,就AC了。
|
虽然这道题目大家做的时候,可能都不会去想什么贪心算法,一鼓作气,就AC了。
|
||||||
|
|
||||||
|
@ -144,6 +144,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
## 类似题目
|
||||||
|
|
||||||
|
* 1254. 统计封闭岛屿的数目
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
|
@ -280,7 +280,7 @@ public class Solution {
|
|||||||
|
|
||||||
## Python
|
## Python
|
||||||
|
|
||||||
```Python3
|
```Python
|
||||||
class TreeNode:
|
class TreeNode:
|
||||||
def __init__(self, val = 0, left = None, right = None):
|
def __init__(self, val = 0, left = None, right = None):
|
||||||
self.val = val
|
self.val = val
|
||||||
|
@ -66,7 +66,7 @@ IDE那么很吃内存,打开个IDE卡半天,用VIM就很轻便了,秒开
|
|||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
PowerVim的安防非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
PowerVim的安装非常简单,我已经写好了安装脚本,只要执行以下就可以安装,而且不会影响你之前的vim配置,之前的配置都给做了备份,大家看一下脚本就知道备份在哪里了。
|
||||||
|
|
||||||
安装过程非常简单:
|
安装过程非常简单:
|
||||||
```bash
|
```bash
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。
|
本周赶上了十一国庆,估计大家已经对本周末没什么概念了,但是我们该做总结还是要做总结的。
|
||||||
|
|
||||||
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简答题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
本周的主题其实是**简单但并不简单**,本周所选的题目大多是看一下就会的题目,但是大家看完本周的文章估计也发现了,二叉树的简单题目其实里面都藏了很多细节。 这些细节我都给大家展现了出来。
|
||||||
|
|
||||||
|
|
||||||
## 周一
|
## 周一
|
||||||
|
Reference in New Issue
Block a user