贪心算法基本介绍以及在lintcode上的典型题型

最初接触贪心算法是在学习数据结构与算法基础时,当时接触了最短路径的迪杰斯特拉算法,这是由一个局部贪心从而实现全局最优的一个典型算法,但是作为一个标准问题的解法它实在是太难自己写出来了,所以自己想深入地了解了一下贪心算法,以达到融会贯通的效果生气


一、什么是贪心算法?


  • 顾名思义该算法重点在于贪心,也就是对于每一个原子事件,都需要做一个当前受益最大的决定
  • 同时做到全局最优
二、贪心算法的特点是什么?

  • 首先是难想,不知道是在何种情况下出现贪心算法,以一个什么事件贪心?
  • 解法通常都十分巧妙,且时间空间复杂度都较低
  • 无后效性,这一点和动态规划算法相似,也正是因为这点,贪心算法都能由动态规划做出(算法导论提及),只是贪心算法的适用范围更小一点。
  • 正确性证明一般来说反而比算法复杂


例题:
1.Lintcode p187加油站:一条环路上有若干个加油站,第i个加油站有gas[i]的汽油,从第i个到第i+1个加油站的路径上需要消耗cost[i]的汽油,你开车从某个加油站出发,初始油量为空,问环绕一周的方案

  • 显然若gas[0]+gas[1]+...+gas[n-1]如果小于cost[0]+cost[1]+...+cost[n-1]的话是不可能有成功方案的
  • 设a[i]=gas[i]-cost[i]
  • 那么这道题就变成了一个数列求和,使得过程中不会出现和小于0的情况
设i=0,如果a[0]>=0则进一步检查a[0]+a[1]以此类推,如果出现小于0的情况,则i直接等于出现异常的pos的下一个点(该算法的关键),理解一下为何。

2.Lintcode p84落单的数(3)给定2n+2个数,其中有n对数字成对出现,找出不一样的2个数。
如果是2n+1个数字,则可以通过逐步位异或运算得到落单的数,但是此题是2n+2个数字。因此需要有所变化:
  • 假设这两个数字是A和B,因为A和B不同,因此异或必然有某一个二进制位k为1,从这位着手,将2n+2个数字分为k位是0还是1的两个部分,显然,这样2n+2个数字又变成了第一种情况。


3.小孩分糖果问题。Lintcode p412

N个小朋友站成一列,每人都有一个聪明值a[i],现在要求分糖果时,如果A比它相邻的B聪明,那么A的糖果必须要多一些,而所有小朋友必须都分到糖果,问怎么分花糖果最少。

显然按照a[i]值分配糖果肯定没问题,但是这样花费糖过多,我们需要尽量少的分配糖,但是如果以每一个小朋友,考虑他相邻的两个小孩为基准,显然难以思考。因此我们可以尝试分为左至右和右至左两种顺序来思考。这样正确性的证明尤为重要。

第一个小孩分1个,
如果a[i]>a[i-1]则,x[i]=x[i-1]+1,否则x[i]=1;
以此类推。
正确性证明:
  • 如果a[i]>a[i-1],而x[i]!=x[i-1]+1,假设有一个满足这条件的最优策略,那么相邻的小孩之间,必然是x[i]>x[i-1]+1,而我们把x[i]减1并不会影响策略的正确性,所以,+1是正确的策略。
  • 类似的证明a[i]<a[i-1]的情况。
然后从另一个方向也遍历一遍,对同一个孩子,取max(x[i],y[i])即可;



典型例题还有p46主元素和p47主元素2,这两题不做赘述了,注意设置一个或者多个计数器(擂台),让数字之间Pk即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值