贪心算法之取手套问题(牛客)
Posted 快乐江湖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心算法之取手套问题(牛客)相关的知识,希望对你有一定的参考价值。
解法框架
待定
手套
这道题的关键点如下
- A先生是无法分辨手套的颜色的,但是能分辨手套的形状,这也意味着他在取手套时并不是随意一把抓,而是可以有目的的取左手套或者右手套(其实我在起初做这道题的时候没有注意这一点,意味是随机一把抓,这无形之中就增大了难度)
- 如果没有至少这个关键词,同时题目又保证了手套绝对是可以匹配的,所以可以全部把左手套拿出来,然后右手套随机取一只
- 有了“至少”后,它就体现了一种贪心的思想——每次局部最优,最后全局最优
- 这道题特别注意手套为0的这种情况,因为一旦某个颜色手套的数目为0,将导致该颜色的手套是不可能匹配的,那么如果还要硬拿出来,无形之中增大了拿取次数
所以本题的解题思路就是,首先拿取左面或右面的手套,使拿取的数目覆盖全部颜色,然后相应的另一半手套只需挑出一即可
以拿出左面为例,有5只颜色不同的左手套
由于无法分辨颜色,所以拿取的时候,如果数目太小,就可能无法覆盖全部手套。比如拿取15只手套,白色的可能就没有覆盖到。所以一旦左面取了15只,就白色的没取,而右面取了一只,恰好就是白色,就导致无法匹配
而如果全取,就不能保证题目“至少”要求了
所以应该这样取:手套数目=总手套数目-最少的颜色的手套+1 。这样取一定可以保证所有手套全部覆盖到
如果一个手套中出现了0,那么将导致对应的手套无法被匹配到,所以这种情况下要把0对应的手套(不管是左还是右都取出来),才能保证不被这种糟糕的情况给破坏掉
最后应该是取左面还是右面的呢?其实这不重要,左面小就取左面的,右面小就取右面的,最后只需在对方手套中取一只即可。
代码
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right)
{
int left_sum=0;
int right_sum=0;//分别计算左面手套和右面手套的综合
int left_min=INT_MAX;
int right_min=INT_MAX;//分别用来保存左面或者右面的最小手套数目
int sum_zero=0;//统计一方出现手套为0的手套数目
for(int i=0;i<n;i++)//有n种颜色的手套
{
if(left[i] * right[i] == 0)//只要一方有0,统计
{
sum_zero+=left[i]+right[i];
}
else
{
left_sum+=left[i];//统计左手套的数目
left_min=min(left_min,left[i]);//左手套中颜色最少的
right_sum+=right[i];//同上
right_min=min(right_min,right[i]);
}
}
//谁少取谁
int get=min(left_sum-left_min+1,right_sum-right_min+1);
return sum_zero+get+1;//最后返回时只要任取对面的1个手套以及取完所有为0的情况和一方手套
}
};
以上是关于贪心算法之取手套问题(牛客)的主要内容,如果未能解决你的问题,请参考以下文章
2020牛客寒假算法基础集训营4.I——匹配星星multiset & 贪心 & 二分
2020牛客寒假算法基础集训营4.E——最小表达式贪心 & 构造