# 总结 使用场景:手动模拟一下感觉可以局部最优推出整体最优,而且想不到反例,那么就试一试贪心。 思路: 假设题干是这样的:给出一系列元素(通常放在一个数组中),请你从中挑选出满足条件的 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]`. 全局最优:找到最短步数达到最长覆盖距离 局部最优:找到当前覆盖区间的元素,使得能最大程度地延长当前覆盖范围。 过程:一开始第一个元素的值就是初始覆盖区间的长度,遍历这个区间的所有元素,找到这样一个元素,它能够最大程度地延长当前覆盖区间,这个元素就是下一跳。在下一个覆盖区间中,再找到同样的元素,这样一直迭代。 ## [452. 用最少数量的箭引爆气球](https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/) 全局: - 限制:射完全部气球 - 目标:消耗的箭的数量最少 局部: - 限制:射箭的范围是当前气球所在的范围 - 目标:这一箭要射穿的气球数量达到最大 算法优化:先对左边界(或右边界)进行排序,以降低时间复杂度。 ## [435. 无重叠区间](https://leetcode.cn/problems/non-overlapping-intervals/) 从左向右记录非交叉区间的个数,用区间总数减去非交叉区间的个数就是需要移除的区间个数了。问题就是要求非交叉区间的最大个数。 先按右边界进行排序。 局部最优:优先选右边界小的区间,所以从左向右遍历,留给下一个区间的空间大一些,从而尽量避免交叉。 全局最优:选取最多的非交叉区间。 ## [56. 合并区间](https://leetcode.cn/problems/merge-intervals/) 先按左边界排序。 局部最优:当前区间能合并出的最长区间 全局最优:合并所有重叠区间 ## [968. 监控二叉树](https://leetcode.cn/problems/binary-tree-cameras/) 局部最优:让叶子节点的父节点安摄像头,所用摄像头最少 全局最优:全部摄像头数量所用最少