leetcode 经典贪心算法题目(思路、方法、code)

用于回顾数据结构与算法时刷题的一些经验记录(提出对应的贪心算法时最好自己举例子试试能否可行)文章目录[455. 分发饼干](https://leetcode-cn.com/problems/assign-cookies/)[376. 摆动序列](https://leetcode-cn.com/problems/wiggle-subsequence/)[402. 移掉K位数字](https://...
摘要由CSDN通过智能技术生成

用于回顾数据结构与算法时刷题的一些经验记录

(提出对应的贪心算法时最好自己举例子试试能否可行)

455. 分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i i i ,都有一个胃口值 g i gi gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j j j,都有一个尺寸 s j sj sj 。如果 s j > = g i sj >= gi sj>=gi,我们可以将这个饼干 j j j分配给孩子 i i i,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正,且一个小朋友最多只能拥有一块饼干。

示例 1:
输入: [1,2,3], [1,1]
输出: 1
解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1

分析:由于每个孩子最多只需要一个饼干,并且我们需要的是满足尽可能多的孩子,因此我们有如下策略

  • 如果一个孩子能被更小的饼干满足,则就应该采用更小的饼干,尽量保留大的饼干给胃口更大的孩子
  • 如果一个饼干不能满足胃口最小的孩子,故它将不能满足每个孩子

因此,我们可以对 饼干尺寸和孩子胃口进行排序,然后遍历饼干尺寸。

  • 如果当前饼干可以满足当前孩子,就满足该孩子,向后遍历饼干和孩子胃口
  • 如果当前饼干不可以满足当前孩子,说明该饼干不会再被利用,向后遍历饼干
  • 如果孩子或者饼干遍历完了,则返回结果即可
class Solution {
   
public:
    int findContentChildren(vector<int>& g, vector<int>& s) 
    {
   
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int cookie=0;  //表示cookie遍历到第几个了 
        int child=0;
        while(child<g.size()&&cookie<s.size())
        {
   
        	if(g[child]<=s[cookie]) //该饼干可以满足孩子,使用即可 
        		child++;  //孩子向后遍历 
        	cookie++;  //饼干向后遍历 
		}
		return child;
    }
};
376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。

分析:

可视化数字发现贪心规律

分析题目可知,实际上摇摆序列就是画到坐标轴上连线后,上下波动的线条的每个顶点。
在这里插入图片描述

因此我们可以将相邻数字之间差计算出来,以次表示两个数字间是上升还是下降关系。 需要注意的是,我们贪心思想表现在,如果出现连续的上升或者下降,则应当取最后一个(即上升或下降最后的端点)作为子序列节点

  • 将相邻数字差表示出来
  • 用一个变量表示当前是处于上升还是下降,发生变化才+1
  • 需要考虑头部是平缓的情况,将其度过
class Solution {
   
public:
    int wiggleMaxLength(vector<int>& nums)
	{
   
		int length=nums.size();
		int result=0;
		if(length<=1) return length;
		for(int i=0;i<length-1;i++) //将差值存入到nums中,共length-1个 
		{
   
			nums[i]=nums[i+1]-nums[i];
		}
		int up_or_down=0;   //0表示当前平,1表示当前为up,2表示当前为down 
		int i=0;
		for(i=0;i<length-1;i++) //将头部的平缓区度过,并初始化up_or_down 
		{
   
				if(nums[i]>0)
				{
   
					up_or_down=1;
					result++;
					break;
				}
				else if(nums[i]<0)
				{
   
					up_or_down=2;
					result++;
					break;
				}
		}
		for(i;i<length-1;i++)
		{
   
			if(nums[i]>0&&up_or_down==2)  //如果当前为下降并且该值为上升,则result+1 
			{
   
				up_or_down=1;
				result++;
				continue;
			}
			else if(nums[i]<0&&up_or_down==1)//如果当前为上升并且该值为下降,则result+1 
			{
   
				up_or_down=2;
				result++;
				continue;
			}
		}
		return result+1;
    }
};
402. 移掉K位数字

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意: num 的长度小于 10002 且 ≥ k。 num 不会包含任何前导零。

示例 1 :
输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3,2 形成一个新的最小的数字 1219

分析:如果给定 “1432219” ,去掉一个数字令其最大,如何去?去掉后肯定减少一位,因此应该尽可能地使高位数最小,分析该数字,由于1<4,故不应该去掉1,否则高位数将增大,4>3,故去掉4,会使得第二位变为3,从而达到尽可能小。

因此去掉数字的原则:从高位向地位遍历,如果对应的数字大于下一位数字,则把该位数字去掉,得到的数字最小

可以用存储结果,这样从高位向地位遍历时如果有错位则将其不加入栈,最终栈中存储内容应该是每一个数字不大于下一位,如果还需要删除,那么我们就将栈顶pop出,直至停止

还需要考虑的是,如果数字中有0出现如何处理(可以考虑将其不放入栈),还要注意的是如何将栈中内容返回所需字符串。

class Solution {
   
public:
    string removeKdigits(string num, int k) 
	{
   
		vector<int> s;  //用vector来表达栈即可,方便遍历元素
		string result="";
		for(int i=0;i<num.length();i++) //循环遍历 
		{
   
			int number=num[i]-'0';
			while(s.size()!=0&&s[s.size()-1]>number&&k>0) //如果当前遍历的数字比前面的数字小,则将前面的数字pop 
			{
   
				s.pop_back();
				k--;
			}
			if(number!=0||s.size()!=0) //0就当作没有,不加入即可 
			{
   
				s.push_back(number);
			} 
		}
		while(s.size()!=0&&k>0) //如果已经遍历完但是还需要删,从尾部删即可 
		{
   
			s.pop_back();
			k--;
		}
		for<
  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值