贪心算法(leetcode分类解题,C++代码详细注释)

贪心算法

  • 前言
  • 455.分发饼干
  • 135.分发糖果
  • 435.无重叠区间
  • 605.种花问题
  • 452.用最小数量的箭引爆气球
  • 763.划分字母区间
  • 122. 买卖股票的最佳时机 II
  • 376. 摆动序列
  • 53. 最大子序和

前言

贪心算法或贪心思想采用贪心的策略,保证每次操作都是局部最优的,从而使最后得到的结果是全局最优的。

455.分发饼干

在这里插入图片描述
题解
因为饥饿度最小的孩子最容易吃饱,所以我们先考虑这个孩子。为了尽量使得剩下的饼干可以满足饥饿度更大的孩子,所以我们应该把大于等于这个孩子饥饿度的、且大小最小的饼干给这个孩子。满足了这个孩子之后,我们同样的策略,考虑剩下孩子里饥饿度最小的孩子,直到没有满足条件的饼干存在。

简而言之,这里的贪心策略是,给剩余孩子里最小饥饿度的孩子分配最小的能饱腹的饼干。

至于具体实现,因为我们需要获得大小关系,一个便捷的方法就是把孩子和饼干分别排序。

这样我们就可以从饥饿度最小的孩子和大小最小的饼干出发,计算有多少个对子可以满足条件。


注意: 对数组或字符串排序是常见的操作,方便之后的大小比较。

注意: 在之后的讲解中,若我们谈论的是对连续空间的变量进行操作,我们并不会明确区分数组和字符串,因为他们本质上都是在连续空间上的有序变量集合。一个字符串“abc”可以被看作一个数组 [‘a’,‘b’,‘c’]。

C++代码

class Solution {
public:int findContentChildren(vector<int>& children, vector<int>& cookies) {sort(children.begin(), children.end());sort(cookies.begin(), cookies.end());int child = 0, cookie = 0;//初始化两个指针,一个指向第一个小孩,另一个指向第一个饼干。while (child < children.size() && cookie < cookies.size()) //指针在正常范围内,运行{if (children[child] <= cookies[cookie]) ++child;//如果第cookie个cookies 比第child个childern大,说明第child个childern可以被满足,于是小孩与饼干指针同时向后移动。++cookie;//如果饼干不能满足小孩,那么饼干指针向下移}//直到某个指针超范围,返回满足的小孩数return child;}
};

135.分发糖果

在这里插入图片描述
解题
虽然这道题leetcode规定为困难,但我觉得这道题是贪心算法中简单的一种。
首先,我们需要初始化一个全为1的数组,从右向左遍历数组,如果左边比右边大,那么左边就在右边基础上加一;再从左向右遍历数组,如果右边比左边大,右边就在左边的基础上加一;
这里的贪心策略就是只考虑相邻两位的关系

代码

class Solution {
public:int candy(vector<int>& ratings) {int size = ratings.size();if(size<2){return size;}//如果只有一个,那么就直接返回1就可以vector<int> nums(size,1);//初始化全为一的数组for(int i = 1;i<size;++i)//从左向右扫描,如果右边比左边大,那么右边在左边的基础上加一{if(ratings[i]>ratings[i-1]){nums[i]=nums[i-1]+1;}}for(int i = size-1;i>0;--i)//从右边向左边扫描,如果右边比左边大,再比较一下是本身大,还是右边加一大。{if(ratings[i-1]>ratings[i]){nums[i-1]= max(nums[i-1],nums[i]+1);}}return accumulate(nums.begin(), nums.end(), 0);//返回数组中所有元素的和}
};

435.无重叠区间

在这里插入图片描述

解题
在选择要保留区间时,我们应该注意区间的结尾,我们选择的区间结尾越小,那么我们保留下来的区间就越多,因此我们采取的贪心策略为,优先保留结尾小且不相交的区间。

那么如何实现呢?
首先,先把区间按照结尾的大小排序;然后,每次选取结尾最小的且和前一个选择的区间不重叠的区间。这就需要用到C++ 的lambda,并结合std::sort()函数进行自定义排序

代码

class Solution {
public:int eraseOverlapIntervals(vector<vector<int>>& intervals) {if(intervals.empty()){return 0;}int n = intervals.size();sort(intervals.begin(),intervals.end(),[](vector<int> a,vector<int> b){return a[1] < b[1];});//C++ lambda函数自定义排序,如果看不懂,请移步C++基础int abandon  = 0,prev = intervals[0][1];//初始化prev指针指向第一组第二个数for(int i = 1;i<n;++i){if(intervals[i][0]<prev)//如果后一组第一个数小于前一组第二个数,说明区间有重复,需要舍弃后一组(原因建见题解),所以abandon加一。{++abandon;}else{prev = intervals[i][1];}//如果后一组第一个数大于这一组第二个数,那么prev指向这一组。}return abandon;}
};

605.种花问题

在这里插入图片描述

题解
这道题的贪心策略就是能种就种

代码

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+1 == flowerbed.size() || flowerbed[i+1] == 0)&& (i == 0 || flowerbed[i-1] == 0))//判读是否能种,能种就种。首先当前位置是0;其次,当前位置是末尾或者下一个位置是0;然后,当前位置是首位,或者前一个位置是0。这样的位置你就可以欢乐的种花花了。{flowerbed[i]= 1;ans += 1;//种花位置加1}}return ans >= n;}
};

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

在这里插入图片描述
题解
这道题看着挺长,其实很简单
leetcode 官方的图,嘿嘿。

注意这是按末尾坐标排序的
排序后如何放箭就显而易见了,第一把箭放在黄色框末尾,第二把箭放在蓝色框框末尾

代码

class Solution {
public:int findMinArrowShots(vector<vector<int>>& points) {if (points.empty()) {return 0;}sort(points.begin(), points.end(), [](const vector<int>& u, const vector<int>& v) {return u[1] < v[1];});//通过C++ lambda函数对每组坐标以末尾进行排序int pos = points[0][1];//初始化第一把箭的位置为第一个气球右坐标。int ans = 1;//如果有气球,一定会使用一支箭。for (const vector<int>& balloon: points) {if (balloon[0] > pos)//如果某个气球的左坐标大于箭的位置,说明它已经超出了第一支箭所能射击的范围,所以箭数加一 ,并将这个气球的右坐标设置为喜下一支箭的初始位置。{pos = balloon[1];++ans;}}return ans;//返回箭数}
};

763.划分字母区间

在这里插入图片描述
题解
遍历字符串,通过哈希表或者数组记录每个字母最后一次出现的位置;再遍历字符串,设遍历第iii个字母,且当前字母最后出现的位置为endiendiendiend=max(end,endi)end = max(end,endi)end=max(end,endi),当i=endi=endi=end时说明前i+1i+1i+1为一个符合题意的片段;初始化startstartstartend+1end+1end+1,重复上述操作
如果理解不了,可以画画,就明白了。

代码

class Solution {
public:vector<int> partitionLabels(string S) {int last[26];//此数组将用于保存每个字母最后出现的位置int length =S.size();for(int i =0;i<length;++i){last[S[i]-'a'] = i;//记录每个字母最后出现的位置}vector<int> partition;int start = 0,end =0;for(int i =0;i<length;++i){end = max(end,last[S[i]-'a']);//寻找边界if(i == end ){partition.push_back(end-start+1);start = end +1;}}return partition;}
};

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

在这里插入图片描述
题解
贪心策略:涨了就卖。至于为什么第二天涨了就卖出呢,因为在持续增长的情况下接连卖出和涨到最高点卖出获利是一样的,所以只要第二天涨了就卖出。

代码

//太简单了,实在是没什么好注释的!!!!
class Solution {
public:int maxProfit(vector<int>& prices) {int res =0;for(int i =1; i < prices.size();++i){if(prices[i]>prices[i-1]){res += prices[i] -prices[i-1];}}return res;}
};

376. 摆动序列

在这里插入图片描述

题解

代码

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {if(nums.size()<2) return nums.size();int cur =0;int pre =0;int result =1;for(int i =1;i<nums.size();++i){cur = nums[i]-nums[i-1];if((pre >= 0 && cur <0) || (pre<=0 && cur>0)){++result;pre =cur;}}return result;}
};

53. 最大子序和

在这里插入图片描述

代码
先来个暴力算法

class Solution {
public:int maxSubArray(vector<int>& nums) {int result = INT32_MIN;int count = 0;for (int i = 0; i < nums.size(); i++) { // 设置起始位置count = 0;for (int j = i; j < nums.size(); j++) { // 每次从起始位置i开始遍历寻找最大值count += nums[j];result = count > result ? count : result;}}return result;}
};

贪心算法


持续更新中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/408239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转]2006年十二星座运程 目录

白羊座2006年运程 金牛座2006年运程 双子座2006年运程 巨蟹座2006年运程 狮子座2006年运程 处女座2006年运程 天秤座2006年运程 天蝎座2006年运程 射手座2006年运程 摩羯座2006年运程 水瓶座2006年运程 双鱼座2006年运程作者Blog&#xff1a;http://blog.csdn.net/cndg…

双指针法(leetcode分类解题,C++代码详细注释)

双指针法前言167.两数之和 II - 输入有序数组88.合并两个有序数组142. 环形链表 II633.平方数之和680. 验证回文字符串 Ⅱ27. 移除元素344. 反转字符串剑指 Offer 05. 替换空格151. 翻转字符串里的单词206.反转链表125. 验证回文串19. 删除链表的倒数第 N 个结点面试题 02.02. …

二分法(leetcode分类解题,C++代码详细注释)

二分法前言69. x 的平方根35. 搜索插入位置前言 二分查找也常被称为二分法或者折半查找&#xff0c;每次查找时通过将待查找区间分成两部分并只取一部分继续查找&#xff0c;将查找的复杂度大大减少。对于一个长度为 O(n) 的数组&#xff0c;二分查找的时间复杂度为 O(log n)。…

ArcGIS 10——地理数据库管理GIS数据

写本文的最初意向是当前正在进行的项目中有实现ESRI版本化数据管理的功能模块&#xff0c;碰到一些棘手的问题&#xff0c;几经周折还是决定系统学习ArcGIS10的帮助文档。&#xff08;文章摘抄的比较多&#xff09; 地理数据库是用于保存数据集集合的“容器”。首先了解一下Arc…

Ubuntu NFS搭建过程

简介 NFS:是Network FileSystem。最大的作用就是通过网络&#xff0c;让不同的机器、不同的作业系统、可以分享档案。通过将共享目录挂接到本地&#xff0c;就可以像操作本地目录一样去操作共享的目录。在共享中分为服务器和客户端,需要安装的程序也不一样&#xff0c;客户端通…

教你如何写框架------用中文构建脚本

框架下载地址&#xff1a; http://files.cnblogs.com/zhangfei/Automation.rar 在看此篇博文前请先理清如下两下博文, 该博文是建立在如下两篇文章的基础上的&#xff1a; http://www.cnblogs.com/zhangfei/p/3456159.htmlhttp://www.cnblogs.com/zhangfei/archive/2012/10/10/…

spring之:XmlWebApplicationContext作为Spring Web应用的IoC容器,实例化和加载Bean的过程...

它既是 DispatcherServlet 的 (WebApplicationContext)默认策略&#xff0c;又是 ContextLoaderListener 创建 root WebApplicationContext(根容器&#xff0c;同时也是 DispatcherServlet 的 WebApplicationContext 的父容器)的默认策略。 继承体系 一、XmlWebApplicationCont…

C++17代码整洁之道

C17代码整洁之道 C代码整洁的基本规范 良好的命名 名称应该自解释使用域中的名称避免使用匈牙利命名法(即名称前加类型)不要通过注释禁用代码 函数 只做一件事情 函数体量要小 当你为函数找到一个富有表现力的名称时,名称中没有连词 圈复杂度低 函数的参数要少 函数尽…