数据结构与算法-贪心算法
往期内容
1-链表
2-栈与队列
3-树与图
4-哈希表
5-查找
6-排序
7-贪心
8-递归与分治
9-动态规划
1.分发饼干
Leetcode-455 分发饼干
思路:排序,优先用较少的饼干满足需求较少的孩子
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
sort(g.begin(),g.end());
sort(s.begin(),s.end());
int g_num=0;
int s_num=0;
while(g_num<g.size() && s_num<s.size())
{
if(g[g_num]<=s[s_num])
{
g_num++;
}
s_num++;
}
return g_num;
}
};
2.摆动序列
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
//状态机的思想
if(nums.size()<2) return nums.size();
static const int BEGIN=0;//三种状态
static const int UP=1;
static const int DOWN=2;
int STATE=BEGIN;
int count=1;
for(int i=1;i<nums.size();i++)
{
switch(STATE)
{
case BEGIN:
{
if(nums[i-1]<nums[i])
{
count++;
STATE=UP;
}
else if(nums[i-1]>nums[i])
{
count++;
STATE=DOWN;
}
else
STATE=BEGIN;
break;
}
case UP:
{
if(nums[i-1]>nums[i])
{
count++;
STATE=DOWN;
}
else
STATE=UP;//此句还可以删除
break;
}
case DOWN:
{
if(nums[i-1]<nums[i])
{
count++;
STATE=UP;
}
break;
}
}
}
return count;
}
};
3.移掉k个数字
class Solution {
public:
string removeKdigits(string num, int k) {
//每次弹出前四个中最大的元素
vector<int> s;
string result="";
for(int i=0;i<num.length();i++)
{
int number=num[i]-0x30;
while(!s.empty() && k>0 && (s.back()>number))
{
s.pop_back();
k--;
}
s.push_back(number);
}
//特殊情况处理
//1.栈不为空,但是还可以删除元素,尾部删除
while(!s.empty() && k>0)
{
s.pop_back();
k--;
}
//2.有0,将前面有零的元素全删除
bool isFirstNotZero=false;
for(int i=0;i<s.size();i++)
{
if(s[i]==0 && !isFirstNotZero)
{
continue;
}
else
isFirstNotZero=true;
result+=(s[i]+0x30);
}
return result==""?"0":result;
}
};
4.跳跃游戏
Leetcode-55 跳跃游戏
思路:定义一个maxs存放每个位置能到达的最远距离,max_index表示能到达的最远距离。依次比较,判断是否能达到最右端
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<int> maxs;
for(int i=0;i<nums.size();i++)
{
maxs.push_back(nums[i]+i);
}
int max_index=maxs[0];//能跳到的最远距离
int i=0;//当前的坐标
while(i<nums.size() && i<=max_index)//i不可能超过数组尾部,也不可能超过最大能跳的范围
{
if(maxs[i]>max_index)
{
max_index=maxs[i];
}
i++;
}
return i>=nums.size()? true:false;
}
};
5.跳跃游戏2
Leetcode-45 跳跃游戏2
思路:发现不能跳跃到更远的地方,才开始跳跃
class Solution {
public:
int jump(vector<int>& nums) {
//思想:发现不能跳跃到更远的地方,才开始跳跃
if(nums.size()<2) return 0;
int current_max_index=nums[0];//当前可达到的最远距离
int pre_max_max_index=nums[0];//遍历过程中可达到的最远距离
int count=1;//最小跳跃次数
for(int i=1;i<nums.size();i++)
{
if(i>current_max_index)//只有当i不能在更新的时候才开始,跳跃
{
current_max_index=pre_max_max_index;
count++;
}
if(pre_max_max_index<(nums[i]+i))
{
pre_max_max_index=nums[i]+i;
}
}
return count;
}
};
6.用最少数量的箭引爆气球
Leetcode-452 用最少数量的箭引爆气球
思路:对气球进行排序,贪心规则:尽可能少的使用箭,通过更新左右区间的方法,直到不得已才使用新的箭
class Solution {
public:
int findMinArrowShots(vector<vector<int>>& points) {
//贪心思想:某个气球至少需要1只弓箭
//击穿该气球的时候,尽可能多的击穿其他更多的气球
if(points.empty()) return 0;
std::sort(points.begin(),points.end(),[](vector<int> &a,vector<int> &b){
return a[0]<b[0];
});
int short_num=1;//弓箭
int left=points[0][0];
int right=points[0][1];
for(int i=1;i<points.size();i++)
{
if(points[i][0]>=left && points[i][0]<=right)//缩小区间,尽可能多的射击气球
{
left=points[i][0];
//if(points[i][1]<=right && points[i][1]>=left)
if(points[i][1]<right)
{
right=points[i][1];
}
}
else
{
short_num++;
left=points[i][0];//更新 新的射击区间
right=points[i][1];
}
}
return short_num;
}
};
7.最低加油次数
Leetcode-871 最低加油次数
思路:设置最大堆,存储经过的加油站中的油,如果不能到达下一加油站,则从大顶堆中取出元素,并记录。
class Solution {
public:
int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
priority_queue<int> Q;//最大堆
int result=0;//加油次数
/*std::sort(stations.begin(),stations.end(),[](vector<int> &a,vector<int> &b){
return a[0]<b[0];
});//停靠点从大到小排序*/
for(int i=0;i<stations.size();i++)
{
Q.push(stations[i][1]);
startFuel=startFuel-stations[i][0];//剩余油量
int nextFuel=startFuel;//下一加油站需要的
int nextdis=stations[i+1][0]-stations[i][0];
while(!Q.empty() && nextdis>nextFuel)//加油
{
nextFuel+=Q.top();
Q.pop();
result++;
}
if(Q.empty() && nextdis>nextFuel)//不加油
{
return -1;
}
startFuel=nextFuel;
target=target-stations[i][0];
}
return result;
}
};
122 买卖股票
方法1:深度优先遍历DFS,所有情况
方法2:贪心
方法3:DP