原题链接: 手套
题目
描述
在地下室里放着n种颜色的手套,手套分左右手,但是每种颜色的左右手手套个数不一定相同。A先生现在要出门,所以他要去地下室选手套。但是昏暗的灯光让他无法分辨手套的颜色,只能分辨出左右手。所以他会多拿一些手套,然后选出一双颜色相同的左右手手套。现在的问题是,他至少要拿多少只手套(左手加右手),才能保证一定能选出一双颜色相同的手套。
给定颜色种数n(1≤n≤13),同时给定两个长度为n的数组left,right,分别代表每种颜色左右手手套的数量。数据保证左右的手套总数均不超过26,且一定存在至少一种合法方案。
测试样例:
输入:4,[0,7,1,6],[1,5,0,6]
返回:10(解释:可以左手手套取2只,右手手套取8只)
解题思路
选出要拿的最少手套数目,
首先,我们可以想到的是左边全拿在和右边的一只进行匹配或者右边全拿在和左边的一只进行匹配,这点可以是可以,不过就不符合题目求取最少手套数目的要求,那么我们就要通过观察进而得出一个关系,就拿 [4,5,3,7,6] 这个当为左手套的种类,共有5种颜色,每个数组下标下都代表一种颜色的手套的个数,要使得左手套能和右手套进行匹配,那么在选取左手套时,我们就必须把它里面的每种颜色都取得一个,如果我们用sum-min(左手套的总数减去左手套中的最小值),便得到22,这种情况是不符合的,为什么呢?我们看原数组中4+5+7+6=22,那么我们就漏掉了一种颜色,所以我们应该再加一个,因此我们最后得到的公式便为 (sum-min+1).
其次,我们还须判断有一边手套颜色数目为0的手套,将这类手套进行累加。
最后,返回累加值以及左右手所取数目的最小值再加1便是最少的手套数目
解题步骤
- 分别进行左右手手套数目的累加以及他们最小值的选取
left_sum += left[i];
left_min = left_min < left[i] ? left_min : left[i];
right_sum += right[i];
right_min = right_min < right[i] ? right_min : right[i];
- 对存在手套颜色数目为0的手套进行累加
if(left[i] * right[i] == 0)
sum += left[i] + right[i];
完整代码
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right) {
// write code here
int left_sum = 0,left_min = INT_MAX;
int right_sum = 0,right_min = 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
{
left_sum += left[i];
left_min = left_min < left[i] ? left_min : left[i];
right_sum += right[i];
right_min = right_min < right[i] ? right_min : right[i];
}
}
return sum + min(left_sum - left_min + 1,right_sum - right_min + 1) + 1;
}
};
运行结果