Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[pull] main from itcharge:main #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pull merged 129 commits into AlgorithmAndLeetCode:main from itcharge:main
May 27, 2022
Merged
Changes from 1 commit
Commits
Show all changes
129 commits
Select commit Hold shift + click to select a range
edf6b32
Create Graph-Bellman-Ford.py
itcharge Mar 20, 2022
afb623a
Update 01.Hash-Table.md
itcharge Mar 21, 2022
5a18692
去除列表中重复题目
itcharge Mar 22, 2022
aeeb26a
更新目录章节列表
Mar 23, 2022
279255b
更新目录章节列表
Mar 23, 2022
a1f3ee0
更新题解列表
Mar 24, 2022
1b4be8a
Update 0001. 两数之和.md
Mar 28, 2022
de513d7
Update 01.Enumeration-Algorithm.md
Mar 28, 2022
19241f7
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
dce7cd0
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
b66ccbd
Update 01.Enumeration-Algorithm.md
Mar 29, 2022
092fa76
更新课程内容链接
Mar 29, 2022
1c77890
更新题解列表
Mar 30, 2022
1ebb2c1
更新课程内容链接
Mar 30, 2022
b6c3567
Update 01.Segment-Tree.md
Apr 1, 2022
5261ecd
Update 0078. 子集.md
Apr 1, 2022
d8949ea
更新题解列表
Apr 1, 2022
d49e419
Create 1450. 在既定时间做作业的学生人数.md
Apr 2, 2022
a12a916
Update LeetCode 解题报告空白.md
Apr 2, 2022
2a8e742
更新题解目录
Apr 2, 2022
8d7d466
Update 0204. 计数质数.md
Apr 6, 2022
c98b70d
Create 1925. 统计平方和三元组的数目.md
Apr 6, 2022
45b74c1
Create 0800. 相似 RGB 颜色.md
Apr 6, 2022
6f01d1c
更新题解列表
Apr 6, 2022
56cec98
Update 02.Algorithm-Complexity.md
Apr 6, 2022
c87996a
Update 0078. 子集.md
Apr 6, 2022
144761a
Update 0090. 子集 II.md
Apr 6, 2022
860f344
Update 剑指 Offer 57 - II. 和为s的连续正数序列.md
Apr 6, 2022
862f2f6
更新章节目录
Apr 7, 2022
c07e2ab
Update 03.LeetCode-Guide.md
Apr 8, 2022
cf216ed
Update 0091. 解码方法.md
Apr 8, 2022
2ce7012
Update 0198. 打家劫舍.md
Apr 8, 2022
c6ab45f
Update 0213. 打家劫舍 II.md
Apr 8, 2022
d616310
Update 1227. 飞机座位分配概率.md
Apr 8, 2022
664351c
Update 1486. 数组异或操作.md
Apr 8, 2022
ee79e53
Update 剑指 Offer II 089. 房屋偷盗.md
Apr 8, 2022
a93edaa
Update 剑指 Offer II 090. 环形房屋偷盗.md
Apr 8, 2022
d2c7af4
Update 0509. 斐波那契数.md
Apr 8, 2022
946591d
Update 0104. 二叉树的最大深度.md
Apr 8, 2022
6f82a91
更新文章代码格式
Apr 8, 2022
7575e44
Update 01.Recursive-Algorithm.md
Apr 8, 2022
31d9afe
Update 01.Recursive-Algorithm.md
Apr 8, 2022
e3c9bf5
Update 01.Recursive-Algorithm.md
Apr 8, 2022
17d0db8
Update 01.Recursive-Algorithm.md
Apr 11, 2022
c132bc5
更改题解标题格式
Apr 12, 2022
5c2dbe6
Update Array-MergeSort.py
Apr 14, 2022
2c373ef
Update 01.Divide-And-Conquer-Algorithm.md
Apr 14, 2022
56e57eb
更新公式格式
Apr 14, 2022
4c788aa
Update 01.Divide-And-Conquer-Algorithm.md
Apr 14, 2022
fbb04e2
Update 01.Recursive-Algorithm.md
itcharge Apr 18, 2022
3b11f52
Update 0303. 区域和检索 - 数组不可变.md
Apr 19, 2022
118b3e1
更新线段树模板
Apr 19, 2022
a0c5060
更新线段树模板
itcharge Apr 19, 2022
a59b2b0
更新题解列表
Apr 20, 2022
01e7dd9
Update 01.Backtracking-Algorithm.md
Apr 20, 2022
f5a441d
更新线段树模板
Apr 21, 2022
d9c77c0
Update 0303. 区域和检索 - 数组不可变.md
Apr 24, 2022
d5c8551
Update 0307. 区域和检索 - 数组可修改.md
Apr 24, 2022
0034d80
Update 0673. 最长递增子序列的个数.md
Apr 24, 2022
934b009
Update 1109. 航班预订统计.md
Apr 24, 2022
1fee32b
Update 1450. 在既定时间做作业的学生人数.md
Apr 24, 2022
ade2d16
Update 0370. 区间加法.md
Apr 24, 2022
a504a23
Create 1310. 子数组异或查询.md
Apr 24, 2022
d58ba3f
Create 0729. 我的日程安排表 I.md
Apr 24, 2022
4cca60b
Create 0731. 我的日程安排表 II.md
Apr 24, 2022
6a19d08
更新题解列表
Apr 24, 2022
4143b23
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
679ac20
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
3722ae9
Update 0046. 全排列.md
Apr 26, 2022
82ed40f
Update 0051. N 皇后.md
Apr 26, 2022
6bfe7db
Update 0078. 子集.md
Apr 26, 2022
7808a33
Update 01.Backtracking-Algorithm.md
Apr 26, 2022
0337985
更新课程信息
Apr 27, 2022
824e3fc
Update 01.Union-Find.md
May 5, 2022
8771e27
Update 01.Graph-Basic.md
May 6, 2022
0b278e3
Update 01.Union-Find.md
May 7, 2022
a55167d
Update 0547. 省份数量.md
May 9, 2022
a02c90f
Update 0990. 等式方程的可满足性.md
May 9, 2022
ffab9eb
更新 并查集文章
May 9, 2022
aa70ec9
更新并查集模板
May 9, 2022
1702217
更新并查集文章
May 9, 2022
76d3ccb
Update 01.Union-Find.md
May 10, 2022
39c00d3
更新贪心算法
May 10, 2022
4906387
Update 0455. 分发饼干.md
May 11, 2022
3fdca82
更新 并查集文章内容
May 11, 2022
ccef0ac
更新 贪心算法文章内容
May 11, 2022
c17114d
Update 0435. 无重叠区间.md
May 11, 2022
bd1586d
Update 0455. 分发饼干.md
May 11, 2022
8ede64f
更新 并查集文章内容
May 11, 2022
50ee50d
Update 01.Greedy-Algorithm.md
May 12, 2022
ed47e94
Create 1710. 卡车上的最大单元数.md
May 12, 2022
2058630
Update 0217. 存在重复元素.md
May 15, 2022
ad0d375
Update 0219. 存在重复元素 II.md
May 15, 2022
1bf455c
Update 0036. 有效的数独.md
May 15, 2022
556b42e
Update Course-Web-03.md
May 16, 2022
1ddf186
更新力扣新域名
May 18, 2022
836a4b2
Create 2276. 统计区间中的整数数目.md
May 18, 2022
7a87eb5
更新题解列表
May 18, 2022
f9ad233
Update 0005. 最长回文子串.md
May 19, 2022
96c49de
Create 1217. 玩筹码.md
May 19, 2022
63546bc
Create 1247. 交换字符使得字符串相同.md
May 19, 2022
f59d852
更新题解列表
May 19, 2022
c072756
Update 1247. 交换字符使得字符串相同.md
May 19, 2022
23a9161
Update 0189. 轮转数组.md
May 20, 2022
99359be
Create 1408. 数组中的字符串匹配.md
May 20, 2022
4a7ac52
Create 2156. 查找给定哈希值的子串.md
May 20, 2022
599bdf3
Update 02.String-Rabin-Karp.md
May 20, 2022
631f9ac
更新题解列表
May 20, 2022
cbd92c5
Update 2156. 查找给定哈希值的子串.md
May 20, 2022
aac56f7
Update 0189. 轮转数组.md
May 23, 2022
1eb829e
Create 1400. 构造 K 个回文字符串.md
itcharge May 23, 2022
676cf1d
Merge branch 'main' of https://github.com/itcharge/LeetCode-Py
itcharge May 23, 2022
7b2a477
Update 1400. 构造 K 个回文字符串.md
May 23, 2022
98f9927
Create 0921. 使括号有效的最少添加.md
May 23, 2022
92e3fa9
Create 1029. 两地调度.md
May 23, 2022
bed1393
Create 1605. 给定行和列的和求可行矩阵.md
May 23, 2022
d7e6d10
Create 0861. 翻转矩阵后的得分.md
May 23, 2022
4858672
更新题解列表
May 23, 2022
5779d8f
Update 0211. 添加与搜索单词 - 数据结构设计.md
May 24, 2022
1091fc3
Create 0846. 一手顺子.md
May 24, 2022
2d93c03
Create 1296. 划分数组为连续数字的集合.md
May 24, 2022
c5147f6
更新题解列表
May 24, 2022
c39e8ea
更新题解列表
May 25, 2022
841f1de
Create 0851. 喧闹和富有.md
May 25, 2022
c5c149e
更新题解列表
May 25, 2022
5723006
Create 0041. 缺失的第一个正数.md
May 26, 2022
e73e9ee
Update 0861. 翻转矩阵后的得分.md
May 26, 2022
b3ce2a4
Create 0201. 数字范围按位与.md
May 26, 2022
c00a40b
更新题解列表
May 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
更新 并查集文章内容
  • Loading branch information
杨世超 committed May 11, 2022
commit 3fdca82b2a2dde4f69a3352e4ca5346c9962d18d
115 changes: 111 additions & 4 deletions Contents/09.Algorithm-Base/05.Greedy-Algorithm/01.Greedy-Algorithm.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,129 @@

#### 1.2.1 贪心选择性质

「贪心选择」指的是问题的全局最优解可以通过一系列局部最优解来求出,即贪心选择来得到
「贪心选择」:指的是一个问题的全局最优解可以通过一系列局部最优解(贪心选择)来得到

也就是说,每一步通过贪心选择出来的局部解一定是全局最优解的一部分。
换句话说,当进行选择时,我们直接做出在当前问题中看来最优的选择,而不用去考虑子问题的解。在做出选择之后,才会去求解剩下的子问题,如下图所示。

![](https://qcdn.itcharge.cn/images/20220511174939.png)

贪心算法在进行选择时,可能会依赖之前做出的选择,但不会依赖任何将来的选择或是子问题的解。运用贪心算法解决的问题在程序的运行过程中无回溯过程。

#### 1.2.2 最优子结构性质

「最优子结构」:指的是当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质,也称此问题满足最优性原理。
「最优子结构」:指的是一个问题的最优解包含其子问题的最优解。

问题的最优子结构性质是该问题能否用贪心算法求解的关键。举个例子,如下图所示,原问题 $S = \left\{ a_1, a_2, a_3, a_4 \right\},ドル在 $a_1$ 步我们通过贪心选择选出一个当前最优解之后,问题就转换为求解子问题 $S_{子问题} = \left\{ a_2, a_3, a_4 \right\}$。如果原问题 $S$ 的最优解可以由「第 $a_1$ 步通过贪心选择的局部最优解」和「 $S_{子问题}$ 的最优解」构成,则说明该问题满足最优子结构性质。

也就是说,如果原问题的最优解包含子问题的最优解,则说明该问题满足最优子结构性质。

![](https://qcdn.itcharge.cn/images/20220511175042.png)

在做了贪心选择后,满足最优子结构性质的原问题可以分解成规模更小的类似子问题来解决,并且可以通过贪心选择和子问题的最优解推导出问题的最优解。

反之,如果不能利用子问题的最优解推导出整个问题的最优解,那么这种问题就不具有最优子结构。

### 1.3 贪心算法正确性的证明

贪心算法最难的部分不在于问题的求解,而在于是正确性的证明。常用的证明方法有「数学归纳法」和「交换论证法」。

## 3. 贪心算法的解题步骤
- **数学归纳法**:先计算出边界情况(例如 $n = 1$)的最优解,然后再证明对于每个 $n,ドル$F_{n + 1}$ 都可以由 $F_n$ 推导出。
- **交换论证法**:从最优解出发,在保证全局最优不变的前提下,如果交换方案中任意两个元素 / 相邻的两个元素后,答案不会变得更好,则可以推定目前的解是最优解。

判断一个问题是否通过贪心算法求解,是需要进行严格的数学证明的。但是在日常写题或者算法面试中,不太会要求大家去证明贪心算法的正确性。

所以,当我们想要判断一个问题是否通过贪心算法求解时,我们可以:

1. **凭直觉**:如果感觉这道题可以通过「贪心算法」去做,就尝试找到局部最优解,再推导出全局最优解。
2. **举反例**:尝试一下,举出反例。也就是说找出一个局部最优解推不出全局最优解的例子,或者找出一个替换当前子问题的最优解,可以得到更优解的例子。如果举不出反例,大概率这道题是可以通过贪心算法求解的。

## 3. 贪心算法三步走

1. **转换问题**:将优化问题转换为具有贪心选择性质的问题,即先做出选择,再解决剩下的一个子问题。
2. **贪心策略**:根据题意选择一种度量标准,制定贪心策略,选取当前状态下「最好 / 最优选择」,从而得到局部最优解。
3. **全局最优解**:根据上一步制定的贪心策略,将贪心选择的局部最优解和子问题的最优解合并起来,得到原问题的最优解。

1. **贪心策略**:指确定贪心策略,选择当前看上去最好的一个。 比如挑选苹果,如果你认为个头大的是最好的,那么每次都从苹果堆 中拿一个最大的作为局部最优解, 贪心策略就是选择当前最大的苹 果。如果你认为最红的苹果是最好的,那么每次都从苹果堆中拿一个 最红的,贪心策略就是选择当前最红的苹果。因此根据求解目标的不 同,贪心策略也会不同。
2. **局部最优解**:指根据贪心策略,一步步地得到局部最优解。 比如第 1 次选一个最大的苹果放起来,记为a 1 ;第2次再从剩下的苹果 中选择一个最大的苹果放起来,记为a 2 ,以此类推。
3. **全局最优解**:指把所有的局部最优解都合成原问题的一个最优解{a 1 ,a 2 ......}。

1. 建立数学模型来描述问题;
2. 把求解的问题分成若干个子问题;
3. 对每一子问题求解,得到子问题的局部最优解;
4. 把子问题的解局部最优解合成原来解问题的一个解。

## 4. 贪心算法的应用

### 4.1 分发饼干

#### 4.1.1 题目链接

- [455. 分发饼干 - 力扣](https://leetcode.cn/problems/assign-cookies/)

#### 4.1.2 题目大意

**描述**:一位很棒的家长为孩子们分发饼干。对于每个孩子 `i`,都有一个胃口值 `g[i]`,即每个小孩希望得到饼干的最小尺寸值。对于每块饼干 `j`,都有一个尺寸值 `s[j]`。只有当 `s[j] > g[i]` 时,我们才能将饼干 `j` 分配给孩子 `i`。每个孩子最多只能给一块饼干。

现在给定代表所有孩子胃口值的数组 `g` 和代表所有饼干尺寸的数组 `j`。

**要求**:尽可能满足越多数量的孩子,并求出这个最大数值。

**说明**:

- 1ドル \le g.length \le 3 * 10^4$。
- 0ドル \le s.length \le 3 * 10^4$。
- 1ドル \le g[i], s[j] \le 2^{31} - 1$。

**示例**:

```Python
输入 g = [1,2,3], s = [1,1]
输出 1
解释 你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1, 2, 3。虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。所以应该输出 1。
```

#### 4.1.3 解题思路

为了尽可能的满足更多的小孩,而且一块饼干不能掰成两半,所以我们应该尽量让胃口小的孩子吃小块饼干,这样胃口大的孩子才有大块饼干吃。

所以,从贪心算法的角度来考虑,我们应该按照孩子的胃口从小到大对数组 `g` 进行排序,然后按照饼干的尺寸大小从小到大对数组 `s` 进行排序,并且对于每个孩子,应该选择满足这个孩子的胃口且尺寸最小的饼干。

下面我们使用贪心算法三步走的方法解决这道题。

1. **转换问题**:将原问题转变为,当胃口最小的孩子选择完满足这个孩子的胃口且尺寸最小的饼干之后,再解决剩下孩子的选择问题(子问题)。
2. **贪心策略**:对于当前孩子,用尺寸尽可能小的饼干满足这个孩子的胃口。
3. **全局最优解**:在上面的贪心策略下,满足胃口的孩子数量达到最大,就是全局最优解。

使用贪心算法的代码解决步骤描述如下:

1. 对数组 `g`、`s` 进行从小到大排序,使用变量 `index_g` 和 `index_s` 分别指向 `g`、`s` 初始位置,使用变量 `res` 保存结果,初始化为 `0`。
2. 对比每个元素 `g[index_g]` 和 `s[index_s]`:
1. 如果 `g[index_g] <= s[index_s]`,说明当前饼干满足当前孩子胃口,则答案数量加 `1`,并且向右移动 `index_g` 和 `index_s`。
2. 如果 `g[index_g] > s[index_s]`,说明当前饼干无法满足当前孩子胃口,则向右移动 `index_s`,判断下一块饼干是否可以满足当前孩子胃口。
3. 遍历完输出答案 `res`。

#### 4.1.4 代码

```Python
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
index_g, index_s = 0, 0
res = 0
while index_g < len(g) and index_s < len(s):
if g[index_g] <= s[index_s]:
res += 1
index_g += 1
index_s += 1
else:
index_s += 1

return res
```

## 参考资料

- 【博文】[贪心 - OI Wiki](https://oi-wiki.org/basic/greedy/)
- 【博文】[贪心算法理论基础 - Carl - 代码随想录](https://github.com/youngyangyang04/leetcode-master/blob/master/problems/贪心算法理论基础.md)
- 【书籍】ACM-ICPC 程序设计系列 - 算法设计与实现 - 陈宇 吴昊 主编

AltStyle によって変換されたページ (->オリジナル) /