贪心算法之取手套问题(牛客)

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心算法之取手套问题(牛客)相关的知识,希望对你有一定的参考价值。

解法框架

待定

手套

在这里插入图片描述

这道题的关键点如下

  1. A先生是无法分辨手套的颜色的,但是能分辨手套的形状,这也意味着他在取手套时并不是随意一把抓,而是可以有目的的取左手套或者右手套(其实我在起初做这道题的时候没有注意这一点,意味是随机一把抓,这无形之中就增大了难度)
  2. 如果没有至少这个关键词,同时题目又保证了手套绝对是可以匹配的,所以可以全部把左手套拿出来,然后右手套随机取一只
  3. 有了“至少”后,它就体现了一种贪心的思想——每次局部最优,最后全局最优
  4. 这道题特别注意手套为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——最小表达式贪心 & 构造

2020牛客寒假算法基础集训营6.C——汉诺塔贪心 & Dilworth定理 & 二分求上升子序列最小化分数

基础算法(数据结构笔试复测Leecode牛客)

部分背包问题-贪心策略

常用算法公式之取模