贪心算法之分糖果
来源:互联网 发布:我的世界清空玩家数据 编辑:程序博客网 时间:2024/06/05 16:45
前几天一位同学向我推荐了一道算法题,想了一会觉得思路有了,然后某天晚上想把代码撸出来,然后没想到的是:“一入此题深似海,从此头发是路人”。
———————————————————————## 标题 ##
题目的意思大致如下:现在你家里有一群小孩,站成一排,你要给他们分糖果。要求是:相邻两个人之间,年龄大的糖果数量要分的多,(如果相邻两个人年龄一样的话,两人的糖果数量大小没有要求)。你的目标是怎么用最少的糖果满足这些孩子的要求。
题目理解还是挺简单的,感兴趣的同学可以先想想看。这是检验智商的时候到了。
接下来,我将给出自己的解答。仅供参考。
刚好前段时间看了一点“贪心算法”。看到题目之后就自然而然的往“贪心”方面去设计。(贪心算法简要的说就是求解一个大问题的最优解时,每一小步都采取当前最优的策略,最终得到整体最优解,还不懂得自行百度吧)然后设计出来的算法就是:从第一个人开始,给他一个糖果,让往后走,若后一个人比前一个人年龄大,则他的糖果在前一个人的基础上加一,如果若后一个人比前一个人年龄小,则他的糖果在前一个人的基础上减一,如果减到零的话,就往前找到糖果一直减少的第一个人,从他开始,往后每人加一个糖果。
举个小例子,比如这群小孩的年龄如下:3,5,10,9,4,3。那么这个算法的执行过程就是,第一个人1个,第二个人2个,第三个人3个。第四个人2个,第五个人1个,此时发现第六个人只有0个了,让就从第三个人开始,每人加一个糖果。最后一个人就可以分一个了。这样就很愉快的完成任务了,花了一点时间把代码敲出来了。好开心。
结果一测试,很多结果不是最优解。吓的我只能重新考虑一下算法。在损伤了一些脑细胞之后发现,”减一“这个操作会有bug。比如上面的例子去掉后面两个人,即3,5,10,9。按照原来的算法是:1,2,3,2。但是你会发现最少的分发其实是:1,2,3,1。这只是一个简单的例子,还有很多更复杂的情况。于是我果断调整策略:每次只要后一个人的年龄比前面一个人小,我就给他一个糖果。遇到某人没有糖果发的时候,处理方法依旧如上。
代码改完之后,果然对了很多,然后发现我还没考虑相等的情况。(原题里也没说相等怎么办,自行脑补了一下)每次遇到相等的情况,就只给他一个。其它处理方法依旧不变。
好了,算法的设计终于告一段落了。但是接下来蛋疼的是撸代码了。可能是好久没编了,即使有了这个算法然后编出来还是有错。具体实现起来还是不简单的。比如怎么记录从谁开始一直下降,还有。。。。。。等细节问题。然后开始调试,各种改动,此处省略一千字。。。接下来附上代码了:
int candy(int* ratings, int ratingsSize) { int min = 0; int number = 1; int current; int i; int count=0; int a; for (a = 0; a < ratingsSize-1; a++) { if(ratings[a]==ratings[a+1]) { break; } else if (ratings[a] > ratings[a + 1]) count++; else break; } min = count+1; for (i = 1; i < ratingsSize; i++) { if (ratings[i]>ratings[i - 1]) { number++; min = min + number; } else if (ratings[i] == ratings[i - 1]) { number = 1; min = min + number; } else { count = 0; for (current = i; current < ratingsSize; current++) { if (ratings[current] < ratings[current - 1]) { count++; min = min + count; } else { break; } } if(count>=number&&i!=1) { min=min+count-number+1; } number = 1; i = current-1; } } return min; }
改了几个错误,提交之后,A了。真是来之不易的幸福,o(* ̄▽ ̄*)o。解释一下代码:第一个for循环是为了处理,前面的人的年龄都相等的情况。直接给他们每人一个。(其实是放在大循环了没改出来,两者的时间复杂度也差不多)。number是记录当前这个人的糖果的数量,遇到后一个人年龄大与等于当前这个人的话,比较好处理。如果后一个人年龄小于前一个人的话,就一直找到年龄开始上升的两个人。计算这段年龄递减的人所需的糖果数量。这个程序虽然有两重循环,但实际上时间复杂度依旧为O(n)。 总的来说,这道题看上去不是很难,但是要想到各种情况的算法还是有一定难度的,可能会遗漏一些情况。这就是算法的严密性。突然记起和某位大佬写一道算法题,就是一个数组中只有一个数出现了一次,其它数都出现了三次,把那个出现一次的数找出来。结果算法逻辑漏了一些情况。在交流的时候还肯定的说我的算法没问题,很简单的解释了一下。结果就很尴尬了,认真一想发现漏了情况,其实算法也就是错的。真是打脸啪啪响。 算法是很挑战思维的东西,能够独立思考出一些算法题是很有成就感,特别是找到了较优 的解法。其次设计的过程中,逻辑关系要理清楚,否则很容易出错或者遗漏情况。比如我现在都不能确定上面的算法是不是符合所有的情况,毕竟平台只有29个测试用例。
- 贪心算法之分糖果
- leetcode 135. Candy 分糖果 + 贪心算法
- 算法题:分糖果
- 蓝桥杯之分糖果
- LeetCode之分糖果
- 【BZOJ2330】 [SCOI2011]糖果 差分约束+贪心
- LeetCode之小孩分糖果
- 算法提高 拿糖果 (贪心啊~)
- 分糖果(图论算法)
- 蓝桥-分糖果(算法训练)
- [牛客网算法笔记]分糖果问题
- 【BZOJ】1045 [HAOI2008] 糖果传递 && 3293 [Cqoi2011]分金币 贪心
- bzoj3293/1045 [Cqoi2011]分金币/[HAOI2008] 糖果传递 贪心
- 分糖果
- 分糖果
- 分糖果
- 分糖果
- 分糖果
- 最长公共子序列
- 《hive编程指南》阅读笔记摘要(七)
- 简单看Spring源码--对xml文件解析
- 【Spring学习19】作用域:使用代理<aop:scoped-proxy/>
- linux CentOS学习笔记之文件系统及权限
- 贪心算法之分糖果
- DetachedCriteria用法
- ThinkPHP的Upload.class.php解析
- java 中的JDBC 进行基础的数据库连接
- redis-08-主从复制
- AtCoder
- ssm框架的理解
- Android Glide框架
- Android例子—HttpURLConnection发送POST、GET请求代码示例