From ef1cab537bd3c5d156f7676b9bb154dc83925c41 Mon Sep 17 00:00:00 2001 From: Sainnhe Park Date: Mon, 6 Feb 2023 17:29:40 +0800 Subject: [PATCH] greedy --- notes/src/SUMMARY.md | 4 ++ notes/src/greedy.md | 114 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 notes/src/greedy.md diff --git a/notes/src/SUMMARY.md b/notes/src/SUMMARY.md index 4b98a36..b65a080 100644 --- a/notes/src/SUMMARY.md +++ b/notes/src/SUMMARY.md @@ -47,6 +47,10 @@ - [排列问题](./permute.md) - [棋盘问题](./chess.md) +# 贪心算法 + +- [总结](./greedy.md) + # STL - [总结](./stl.md) diff --git a/notes/src/greedy.md b/notes/src/greedy.md new file mode 100644 index 0000000..d38bed0 --- /dev/null +++ b/notes/src/greedy.md @@ -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]`. + +全局最优:找到最短步数达到最长覆盖距离 + +局部最优:找到当前覆盖区间的元素,使得能最大程度地延长当前覆盖范围。 + +过程:一开始第一个元素的值就是初始覆盖区间的长度,遍历这个区间的所有元素,找到这样一个元素,它能够最大程度地延长当前覆盖区间,这个元素就是下一跳。在下一个覆盖区间中,再找到同样的元素,这样一直迭代。