leetcode——我贪之贪得无厌之不能再贪之贪心算法(c++系列题目)

编程入门 行业动态 更新时间:2024-10-09 08:37:26

leetcode——我贪之<a href=https://www.elefans.com/category/jswz/34/1719593.html style=贪得无厌之不能再贪之贪心算法(c++系列题目)"/>

leetcode——我贪之贪得无厌之不能再贪之贪心算法(c++系列题目)

  • 我来填坑了,这篇博客给大家带来的是我贪之贪得无厌之不能再贪之贪心算法系列题目,期中很多到题我都是搬的题解,主要是理解其中的思路,如有侵权,联系侵删啊。
  • 建议大家自己还是手动去刷一下这些题,这些题都比较经典,手刷一遍印象更深。
  • 还有强烈大家关注406和763,这两题不是一般的贪,而是那种神奇巧妙的贪,我愿称其为贪中之贪

题目列表

    • 455. 分发饼干
    • 435. 无重叠区间
    • 452. 用最少数量的箭引爆气球
    • 406. 根据身高重建队列
    • 121. 买卖股票的最佳时机
    • 122. 买卖股票的最佳时机II
    • 605. 种花问题
    • 665. 非递减数列
    • 53. 最大子序和
    • 763. 划分字母区间

455. 分发饼干

  • 贪心,直接给两个数组排序(从小到大),依次比较即可,如果当前饼干小于当前孩子胃口,说明该饼干一个都满足不了,直接用下块跟当前孩子比即可,直到两个数组有一个遍历完即可。
class Solution {
public:int findContentChildren(vector<int>& g, vector<int>& s) {if( g.size() == 0 || s.size() ==0) return 0;sort(g.begin(),g.end());sort(s.begin(),s.end());int gi = 0,si = 0;while(gi < g.size() && si < s.size()){if(g[gi] <= s[si]){gi++;}si++;}return gi;}
};

435. 无重叠区间


  • 贪! 将区间按结束时间从小到大排序,获取最小的区间终结点,如果区间的起点,小于上一个区间的终点,说明有交集,要删除;没有交集,更新终结点。
  • 注意: Leecode的sort的bool要加static变量,否则会报错
class Solution {
public:static bool cmp(vector<int> a, vector<int> b){return a[1] < b[1];}int eraseOverlapIntervals(vector<vector<int>>& intervals) {if(intervals.size() == 0)return 0;//按照区间终结点,从小到大排序sort(intervals.begin(),intervals.end(),cmp);int end = intervals[0][1];int ans = 0;for(int i = 1 ; i < intervals.size(); i++){if(intervals[i][0] < end){ans++;}else{end = intervals[i][1];}}return ans;}
};

452. 用最少数量的箭引爆气球

  • 该题也是计算不重叠的区间个数,不过和上题的区别在于,[1, 2] 和 [2, 3] 在本题中算是重叠区间。思路和上题一样,判断条件不同即可。
class Solution {
public:static bool cmp(vector<int> a, vector<int> b){return a[1] < b[1];}int findMinArrowShots(vector<vector<int>>& points) {if(points.size()==0){return 0;}sort(points.begin(),points.end(),cmp);int ans = 1;int end = points[0][1];for(int i = 1; i < points.size(); i++){if(points[i][0] > end){ans++;end = points[i][1];}}return ans;}
};

406. 根据身高重建队列

  • 这个题贪的有点意思啊,因为个子矮的人相对于个子高的人是看不见的。。。是看不见的。。。不见的。。。 因此后面可以按序插入,经典啊,牛逼啊,是不是没想到
  • 先按身高h降序排,再按k升序排,然后依次插入到k下标即可,是不是很神奇,我也觉的很神奇,学到了。

防止某些同学学不会,我直接上图手把手交你贪啊要个赞不过分吧





class Solution {
public://先按身高h降序排,再按k升序排static bool cmp(vector<int> a, vector<int> b){if(a[0] == b[0])return a[1] < b[1];return a[0] > b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort(people.begin(),people.end(),cmp);//使用链表可以优化性能list<vector<int>> r;for (auto& e : people) {auto pos = r.begin(); //lsit不支持随机访问advance(pos, e[1]);   //使迭代器前进或后退n个位置。r.insert(pos, e);}return std::vector<vector<int>>(r.begin(), r.end());//下面是vector板的插入,性能没有链表好// vector<vector<int>> res;// for (auto& e : people) //       res.insert(res.begin() + e[1], e);// return res;}
};

121. 买卖股票的最佳时机

  • 别想,贪!!! 默认将第一天当成股票买入最低点,从第二天开始遍历,如果该天比最低点小,记录该点即可,否则用看今天的收益是否大于最大值,大于则替换。遍历一便结果就出来了。注意会给空数组的情况。
class Solution {
public:int maxProfit(vector<int>& prices) {if(prices.size() == 0) return 0;int ans = 0;int minx = prices[0];for(int i = 1 ; i < prices.size(); i++){if(prices[i] < minx){minx = prices[i];}else if(prices[i] - minx > ans){ans = prices[i] - minx;}}return ans;}
};

122. 买卖股票的最佳时机II


  • 别问,问就是贪,原则就是所有上涨交易日都买卖(赚到所有利润),所有下降交易日都不买卖(永不亏钱)。(加所有的上升段)
class Solution {
public:int maxProfit(vector<int>& prices) {int ans = 0;for(int i = 1; i < prices.size() ; i++){int x = prices[i] - prices[i-1];if(prices[i] - prices[i-1] > 0){ans += prices[i] - prices[i-1];}}return ans;}
};

605. 种花问题


  • 这个题应该算贪吧,我们从左到右扫描数组,如果数组中有一个 0,并且这个 0 的左右两侧都是 0,那么我们就可以在这个位置种花,即将这个位置的 0 修改成 1,并将计数器 count 增加 1。
  • 注意:对于数组的第一个和最后一个位置,我们只需要考虑一侧是否为 0
class Solution {
public:bool canPlaceFlowers(vector<int>& flowerbed, int n) {int ans = 0;for(int i = 0; i < flowerbed.size();i++){if(flowerbed[i] == 0 && ( i == 0 || flowerbed[i - 1] == 0 ) && ( i == flowerbed.size()-1 || flowerbed[i + 1] == 0 )){flowerbed[i] = 1;ans++;}if(ans >= n)return true;}return false;}
};

665. 非递减数列

  • 这道题给了我们一个数组,说我们最多有1次修改某个数字的机会,
  • 问能不能将数组变为非递减数组。题目中给的例子太少,不能覆盖所有情况,我们再来看下面三个例子:

4,2,3 -> 2,2,3
1,4,2,3 -> 1,2,2,3
2,3,3,2,4 -> 2,3,3,3,4

  • 我们通过分析上面三个例子可以发现,当我们发现后面的数字小于前面的数字产生冲突后,有的时候改前面的数字,有点时候改后面的数子,两者直接有什么关系呢?贪,往前在看一个数字:
  • 首先如果再前面的数不存在,改前面,比如例子[1],4前面没有数字了,我们直接修改前面的数字为当前的数字2即可。
  • 而当再前面的数字存在,并且小于当前数时,改前面,比如例子[2],1小于2,我们还是需要修改前面的数字4为当前数字2;
  • 如果再前面的数大于当前数,改后面,比如例子[3],3大于2,我们需要修改当前数2为前面的数字3。
class Solution {
public:bool checkPossibility(vector<int>& nums) {int cnt = 0;for(int i = 1; i < nums.size() && cnt < 2; i++){if(nums[i-1] <= nums[i]){continue;}cnt++;if(i - 2 >= 0 && nums[i-2] > nums[i]){nums[i] = nums[i-1];}else{nums[i-1] = nums[i];}}return cnt < 2;}
};

53. 最大子序和

  • 直接贪,从左往右迭代,一个个数字的加过去,如果sum<0;重当前开始找字串。
  • 如上面的例子,默认sum=num[0],从下标为1开始。当下标为1时,sum = -2小于0,所以从sum=num[1];下标为2时,sum=1大于0,所以sum+=nums[2]直接加上当前值。依次类推。这还听不懂的话,直接上图再次手把手交你贪啊





class Solution {
public:int maxSubArray(vector<int>& nums) {if(nums.size()==0)return 0;int preSum  = nums[0];int ans = preSum;for(int i = 1;i < nums.size();i++){preSum = preSum > 0?preSum + nums[i]:nums[i];ans = max(preSum,ans);}return ans;}
};

763. 划分字母区间

  • 这道题,是真的贪,而且贪的还很巧妙很神奇,我愿称其为贪中之经典。
  • 思路如下: 注意题目要求啊,要尽可能的划分更多的片段,先确定思路:看见开头一个字母,就要看这个字母最后出现在哪,然后看看这个开头和结尾之间的那些其他字母是不是都落在这个区间里,如果不是,则扩充区间,如果是,那就最好了
  • 对于这道题,一个关键点是利用数组记载一个字母最后出现的位置index。
  • 然后,遍历字符串并跟它比较,用max函数来看看是边界大还是当前遍历的这个字母的最大index大
  • 如果当前遍历字母的最大index大,那就说明超过了边界,那就要更新边界,大概就是这个思路。 结合我说的,康康下面的代码哈。
class Solution {
public:vector<int> partitionLabels(string S) {int len = S.length();vector<int> ends(26,-1);//记录每个字母最后出现的次数。for(int i = 0; i < len; i++){ends[S[i]-'a'] = i;}vector<int> ans;int i = 0;while(i < len){//记录第一个字符的最后出现的位置int r = ends[S[i] - 'a']; //遍历第一个字符到最后一个字符间的每个字符是否都在区间内     for(int j = i; j <= r; j++){//不在区间内,则更新区间if(ends[S[j]-'a'] > r){r = ends[S[j]-'a'];}}ans.push_back(r - i + 1);i = r + 1;}return ans;}
};

看完了,学会了没?点个赞呗。

更多推荐

leetcode——我贪之贪得无厌之不能再贪之贪心算法(c++系列题目)

本文发布于:2024-03-11 17:25:08,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1729493.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:贪得无厌   能再   贪心   算法   题目

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!