![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
贪心算法
文章平均质量分 58
想名字多费事
编程小白入驻
展开
-
监控二叉树
思路这道题目首先要想,如何放置,才能让摄像头数最小呢?然后我们发现题目示例中的摄像头都没有放在叶子节点上!这是很重要的一个线索,摄像头可以覆盖上中下三层,如果把摄像头放在叶子节点上,就浪费的一层的覆盖。所以把摄像头放在叶子节点的父节点位置,才能充分利用摄像头的覆盖面积。为什么不从头结点开始看起呢,为啥要从叶子节点看呢?因为头结点放不放摄像头也就省下一个摄像头, 叶子节点放不放摄像头省下了的摄像头数量是指数级别的。所以我们要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体.原创 2021-05-30 17:05:00 · 165 阅读 · 0 评论 -
单调递增的数字
暴力解法时间复杂度:O(n * m) m为n的数字长度空间复杂度:O(1)class Solution {private: //检查数字是否是升序排列,思路是先获取末尾个位数字,用一个10比较所获取的个位数字,若当前MAX的数值比个位数字大,则更新个位数字为MAX的值。 bool checkNum(int num) { int max = 10; while (num) { int t = num % 10;//获取末尾数字 .原创 2021-05-30 15:28:17 · 124 阅读 · 0 评论 -
合并区间-哦吼
思路大家应该都感觉到了,此题一定要排序,那么按照左边界排序,还是右边界排序呢?都可以!那么我按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。局部最优可以推出全局最优,找不出反例,试试贪心。那有同学问了,本来不就应该合并最大右边界么,这和贪心有啥关系?有时候贪心就是常识!哈哈按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左边界 &.原创 2021-05-29 16:58:19 · 73 阅读 · 0 评论 -
划分字母区间
思路一想到分割字符串就想到了回溯,但本题其实不用回溯去暴力搜索。题目要求同一字母最多出现在一个片段中,那么如何把同一个字母的都圈在同一个区间里呢?如果没有接触过这种题目的话,还挺有难度的。在遍历的过程中相当于是要找每一个字母的边界,「如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了」。此时前面出现过所有字母,最远也就到这个边界了。可以分为如下两步:1、统计每一个字符最后出现的位置2、从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了.原创 2021-05-29 15:52:37 · 88 阅读 · 0 评论 -
无重叠区间
看到这道题目都冥冥之中感觉要排序,但是究竟是按照右边界排序,还是按照左边界排序呢?」这其实是一个难点!按照右边界排序,就要从左向右遍历,因为右边界越小越好,只要右边界越小,留给下一个区间的空间就越大,所以从左向右遍历,优先选右边界小的。按照左边界排序,就要从右向左遍历,因为左边界数值越大越好(越靠右),这样就给前一个区间的空间就越大,所以可以从右向左遍历。如果按照左边界排序,还从左向右遍历的话,要处理各个区间右边界的各种情况。「我先来按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减.原创 2021-05-28 17:32:09 · 178 阅读 · 0 评论 -
用最少数量的箭引爆气球
思路如何使用最少的弓箭呢?直觉上来看,貌似只射重叠最多的气球,用的弓箭一定最少,那么有没有当前重叠了三个气球,我射两个,留下一个和后面的一起射这样弓箭用的更少的情况呢?尝试一下举反例,发现没有这种情况。那么就试一试贪心吧!局部最优:当气球出现重叠,一起射,所用弓箭最少。全局最优:把所有气球射爆所用弓箭最少。「算法确定下来了,那么如何模拟气球射爆的过程呢?是在数组中移除元素还是做标记呢?」如果真实的模拟射气球的过程,应该射一个,气球数组就remove一个元素,这样最直观,毕竟气球被射了。但仔细.原创 2021-05-28 16:21:15 · 102 阅读 · 0 评论 -
根据身高重建队列
思路本题有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后在按照另一个维度重新排列。其实如果大家认真做了贪心算法:分发糖果,就会发现和此题有点点的像。在贪心算法:分发糖果的时候说过遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。「如果两个维度一起考虑一定会顾此失彼」。对于本题令人困惑的点是先确定k还是先确定h呢,也就是究竟先按h排序呢,还先按照k排序呢?如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。那.原创 2021-05-27 17:00:37 · 157 阅读 · 0 评论 -
柠檬水找零
这道题目刚一看,可能会有点懵,这要怎么找零才能保证完整全部账单的找零呢?「但仔细一琢磨就会发现,可供我们做判断的空间非常少!」只需要维护三种金额的数量5,10和20。有如下三种情况:情况一:账单是5,直接收下。情况二:账单是10,消耗一个5,增加一个10情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5此时大家就发现 情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。而情况三逻辑也不复杂甚至感觉纯模拟就可以了,其实情况三这里是有贪心的。账单.原创 2021-05-27 16:31:27 · 59 阅读 · 0 评论 -
分发糖果!
思路这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,「如果两边一起考虑一定会顾此失彼」。先确定右边评分大于左边的情况(也就是从前向后遍历)此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果局部最优可以推出全局最优。如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个,所以贪心:candyVec[i] = candyVec[i .原创 2021-05-26 20:01:36 · 126 阅读 · 0 评论 -
加油站(暴力+贪心)
暴力方法暴力的方法很明显就是O(n^2)的,遍历每一个加油站为起点的情况,模拟一圈。如果跑了一圈,中途没有断油,而且最后油量大于等于0,说明这个起点是ok的。暴力的方法思路比较简单,但代码写起来也不是很容易,关键是要模拟跑一圈的过程。「for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历,要善于使用while!」时间复杂度O(n^2)空间复杂度O(n)class Solution {public: int canCompleteCircuit(vector<in.原创 2021-05-26 17:23:28 · 136 阅读 · 0 评论 -
摆动序列-
本题说可以通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。相信这么一说吓退不少同学,这要求最大摆动序列又可以修改数组,这得如何修改呢?来分析一下,要求删除元素使其达到最大摆动序列,应该删除什么元素呢?用示例二来举例,如图所示:「局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值」。「整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列」。局部最优推出全局最优,并举不出反例,那么试试贪心!(为方便表述,以下说的.原创 2021-05-25 21:33:14 · 66 阅读 · 0 评论 -
K次取反后最大化的数组和
贪图思路:局部最优:让绝对值大的负数变为正数,当前数值达到最大。整体最优:整个数组和达到最大。局部最优可以推出全局最优。那么如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让 数组和 达到最大。那么又是一个贪心:局部最优:只找数值最小的正整数进行反转,当前数值可以达到最大(例如正整数数组{5, 3, 1},反转1 得到-1 比 反转5得到的-5 大多了)全局最优:整个数组和达到最大。这么一道简单题,就用了两次贪心!!!!!!!!!那么本题的解题步.原创 2021-05-25 21:29:35 · 124 阅读 · 0 评论 -
跳跃游戏
刚看到本题一开始可能想:当前位置元素如果是3,我究竟是跳一步呢,还是两步呢,还是三步呢,究竟跳几步才是最优呢?其实跳几步无所谓,关键在于可跳的覆盖范围!不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。这个范围内,别管是怎么跳的,反正一定可以跳过来。「那么这个问题就转化为跳跃覆盖范围究竟可不可以覆盖到终点!」每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。「贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后.原创 2021-05-24 14:27:37 · 83 阅读 · 1 评论 -
买卖股票的最佳时机II
思路本题首先要清楚两点:1、只有一只股票!2、当前只有买股票或者卖股票的操作3、想获得利润至少要两天为一个交易单元。这道题目可能我们只会想,选一个低的买入,在选个高的卖,在选一个低的买入…循环反复。「如果想到其实最终利润是可以分解的,那么本题就很容易了!」如果分解呢?假如说我们买了一只股票,第一天买入,是没有利润的,假如这支股票有效期是7天。在这七天里我们只要持有股票,他每天的利润是有变化的。假如第0天买入,第3天卖出,那么利润为:prices[3] - prices[0]。相当于(p.原创 2021-05-24 13:32:38 · 74 阅读 · 0 评论 -
删数
思路#include <bits/stdc++.h>using namespace std;string remove(const string &s) { for (int i = 0; i + 1 < s.size(); ++i) { /* 出现逆序 删除更大的字符 */ if (s[i] > s[i + 1]) return s.substr(0, i) + s.substr(i + 1); } /.原创 2021-05-23 17:31:38 · 66 阅读 · 0 评论 -
最大子序和
暴力解法暴力解法的思路,第一层for 就是设置起始位置,第二层for循环遍历数组寻找最大和。//时间复杂度:O(n^2) 空间复杂度:O(1)class Solution {public: int maxSubArray(vector<int>& nums) { int res=INT_MIN; int count=0; for(int ii=0;ii<nums.size();ii++){ // 设置起始位置 .原创 2021-05-23 14:55:05 · 94 阅读 · 0 评论 -
分发饼干
为了了满足更多的小孩,就不要造成饼干尺寸的浪费。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。「这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩」。可以尝试使用贪心策略,先将饼干数组和小孩数组排序。然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。如图:这个例子可以看出饼干9只有喂给胃口为7的小孩,这样才是整体最优解,并想不出反例,那么就可以撸代码了。初版class Solutio.原创 2021-05-22 13:30:32 · 83 阅读 · 0 评论 -
谈谈贪心算法
什么是贪心「贪心的本质是选择每一阶段的局部最优,从而达到全局最优」。这么说有点抽象,来举一个例子:例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?指定每次拿最大的,最终结果就是拿走最大数额的钱。每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。再举一个例子如果是 有一堆盒子,你有一个背包体积为n,如何把背包尽可能装满,如果还每次选最大的盒子,就不行了。这时候就需要动态规划。贪心的套路(什么时候用贪心)「说实话贪心算法并没有固定的套路」。所以唯一的难点就是如原创 2021-05-22 11:23:44 · 117 阅读 · 0 评论