[每日一题] 30. 手套(数学、模拟、贪心法)

1. 题目来源

链接:手套
来源:牛客网

2. 题目说明

在地下室里放着n种颜色的手套,手套分左右手,但是每种颜色的左右手手套个数不一定相同。A先生现在要出门,所以他要去地下室选手套。但是昏暗的灯光让他无法分辨手套的颜色,只能分辨出左右手。所以他会多拿一些手套,然后选出一双颜色相同的左右手手套。现在的问题是,他至少要拿多少只手套(左手加右手),才能保证一定能选出一双颜色相同的手套。

给定颜色种数n(1≤n≤13),同时给定两个长度为n的数组left,right,分别代表每种颜色左右手手套的数量。数据保证左右的手套总数均不超过26,且一定存在至少一种合法方案。

输入描述:

4,[0,7,1,6],[1,5,0,6]

输出描述:

返回:10(解释:可以左手手套取2只,右手手套取8只)

3. 题目解析

本题的意思是随意取出的手套至少可以形成一组组合的最少手套数量。题目给的两个数组对应位置表示同一种颜色的 左右手套数量。

对于非0递增序列( a 1 a_1 a1< a 2 a_2 a2 < a 3 a_3 a3 < … < a n a_n an)如何覆盖每一个种类呢?
举一个小例子:在2 3 4 5的序列中任意找三个数求和,保证没有其他的三个数的和大于它,你肯定会选择3,4,5;那如果需要找一个整数比其中任意三个数的和都大,且为最小的一个,应该怎么选?
答案为:((2 + 3 + 4 + 5)- 2)+ 1 即可保证序列中任取三个数不可能比它大,且为符合条件 的最小值。
覆盖(a1,a2,…an)的数为(sum( a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an) - a 1 a_1 a1) + 1;// a 1 a_1 a1的值为最小值

对于非0递增序列 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an,要想最终取值覆盖每一个种类 n=sum( a 1 . . . a n a_1...a_n a1...an)- a 1 + 1 a_1+1 a1+1(也就是总数减去最小值之后加一) 同理对于左右手手套颜色都有数量的序列,想要覆盖每一种颜色,则最小数量leftsum = 左边数量和 - 左边最小值+1,rightsum=右边数量和 - 右边的最小值 +1。而对于有0存在的,则需要做累加,保证覆盖每一种颜色。

4. 代码展示

class Gloves {
public:
    int findMinimum(int n, vector<int> left, vector<int> right) {
        // write code here
        int leftSum = 0, leftMin = INT_MAX;
        int rightSum = 0, rightMin = INT_MAX;
        int sum = 0;
        
        // 遍历每一种颜色的左右手套序列
        for (int i = 0; i < n; ++i) {
            // 对于有0存在的颜色手套,累加
            if (left[i] * right[i] == 0)
                sum += left[i] + right[i];
            else {
                leftSum += left[i];
                rightSum += right[i];
                leftMin = min(leftMin, left[i]);
                rightMin = min(rightMin, right[i]);
            }
        }
        // 结果为有左右都有数量的手套序列的结果+有0存在的手套数+1,即能够保证
        return sum + min(leftSum - leftMin + 1, rightSum - rightMin + 1) +1;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值