greedy
All checks were successful
ci/woodpecker/push/test Pipeline was successful

This commit is contained in:
Sainnhe Park 2023-02-06 17:29:40 +08:00
parent 2aee636736
commit ef1cab537b
2 changed files with 118 additions and 0 deletions

View File

@ -47,6 +47,10 @@
- [排列问题](./permute.md)
- [棋盘问题](./chess.md)
# 贪心算法
- [总结](./greedy.md)
# STL
- [总结](./stl.md)

114
notes/src/greedy.md Normal file
View File

@ -0,0 +1,114 @@
# 总结
使用场景:手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。
思路:
假设题干是这样的:给出一系列元素(通常放在一个数组中),请你从中挑选出满足条件的 N 个数,使得总和最大。
来分析一下题干:
- 一系列元素,这是 base
- 满足条件的 N 个数,这是限制条件
- 总和最大,这是全局最优的优化目标
贪心算法是怎样的呢?就是直接找全局最优一般不好找,我们可以在 base 上找局部最优,比如我们可以这么设计:
- 总和大于 0 的一段连续子数组,这是限制条件
- 长度最长,这是局部最优的优化目标
限制条件和优化目标都不一定要和全局最优一样,但是这里有个关键:
你在找局部最优的过程中可以推导出全局最优。
注意,不是从所有局部最优的结果中推导出全局最优的结果,而是你在寻找局部最优的过程中可以找到全局最优。
什么意思?
假设你找到了 K 个局部最优结果,但我们并不是要从这 K 个结果中推出全局最优,而是在你找这 K 个结果的过程中,我们可以用一个变量 `record` 来记录某些东西,然后由这个变量 `record` 和这 K 个局部最优结果共同推导出全局最优解。
---
## [53. 最大子序和](https://leetcode.cn/problems/maximum-subarray/)
> Given an integer array `nums`, find the subarray with the largest sum, and return its _sum_.
>
> ```text
> Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
> Output: 6
> Explanation: The subarray [4,-1,2,1] has the largest sum 6.
> ```
全局:
- 限制:连续子数组
- 目标:总和最大
局部:
- 限制:连续子数组,总和大于零
- 目标:该子数组长度最长
过程:
在找最长子数组时用一个变量 `count` 记录当前总和,用一个变量 `max` 记录最大总和。
- `if (count > max) max = count`
- `if (count < 0) count = 0`
## [122. 买卖股票的最佳时机 II](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/)
> You are given an integer array `prices` where `prices[i]` is the price of a given stock on the `ith` day.
>
> On each day, you may decide to buy and/or sell the stock. You can only hold **at most one share** of the stock at any time. However, you can buy it then immediately sell it on the **same day**.
>
> Find and return the **_maximum_** profit you can achieve.
>
> ```text
> Input: prices = [7,1,5,3,6,4]
> Output: 7
> Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
> Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
> Total profit is 4 + 3 = 7.
> ```
全局目标:总利润最大
局部目标:最长上升区间
过程:找到每个最长上升区间,将每个上升区间的利润加起来就是总利润了。
## [55. 跳跃游戏](https://leetcode.cn/problems/jump-game/)
> You are given an integer array `nums`. You are initially positioned at the array's **first index**, and each element in the array represents your maximum jump length at that position.
>
> Return `true` _if you can reach the last index_, or `false` _otherwise_.
>
> ```text
> Input: nums = [2,3,1,1,4]
> Output: true
> Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
> ```
全局最优:找到最长覆盖距离
局部最优:找到当前区间的最长覆盖距离
过程:一开始第一个元素的值就是初始覆盖区间的长度,遍历这个区间的所有元素,看看能不能找到能延长当前区间覆盖距离的元素,并延长区间覆盖距离,这样一直迭代,看它能不能到达数组末尾。
## [45. 跳跃游戏 II](https://leetcode.cn/problems/jump-game-ii/)
> You are given a **0-indexed** array of integers `nums` of length `n`. You are initially positioned at `nums[0]`.
>
> Each element `nums[i]` represents the maximum length of a forward jump from index `i`. In other words, if you are at `nums[i]`, you can jump to any `nums[i + j]` where:
>
> - `0 <= j <= nums[i]` and
> - `i + j < n`
>
> Return _the minimum number of jumps to reach_ `nums[n - 1]`. The test cases are generated such that you can reach `nums[n - 1]`.
全局最优:找到最短步数达到最长覆盖距离
局部最优:找到当前覆盖区间的元素,使得能最大程度地延长当前覆盖范围。
过程:一开始第一个元素的值就是初始覆盖区间的长度,遍历这个区间的所有元素,找到这样一个元素,它能够最大程度地延长当前覆盖区间,这个元素就是下一跳。在下一个覆盖区间中,再找到同样的元素,这样一直迭代。