分析:我们先不考虑 拿到的手套只数 ,
①最 粗暴 的拿法就是把全部手套都拿出来。此时数量为 左手手套总数 + 右手手套总数。
②思考 进一步的优化方式, 把一只手的手套全部拿出来,另一只手的手套拿一只,必定可以组成一双。此时数量为 min(左手手套总数,右手手套总数)+ 1 。
③能不能再进一步优化呢? 可以!我们统计出 一只手的手套总数count 和 数量最少的某种颜色的手套数min。我们再这一堆里取 count-min+1 只手套,也可以确保拿到了所有颜色的手套最少一只。
④前边的思考看似非常爽,但是这会带来一个致命的BUG,如果只拿一直手套的那边对应的手套数为0,那我们依旧不能凑成一对。那怎么办呢?看来这道题的坑就在一于这个0,因此我们想办法消除这个。
终极解法:当一边一种颜色手套数为0时,就把另一只手相同颜色的手套全拿出来,使两边不会出现一种颜色你有我没有的情况。我们只需要考虑剩下的颜色就好了,就可以用上边第③步的方法来做。
代码如下
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right) {
int count = 0; //左右手拿到的手套总数
int left_count = 0,right_count = 0; //左右手的手套总数
int left_min = INT_MAX,right_min = INT_MAX;//分别是左右手数量最少的某种颜色的数量。
for(int i = 0;i < n;++i)
{
if(left[i]==0)
{
//左手没有这个颜色, 就从右手的手套里把对应的数量拿出来。因为颜色看不见,所有拿的可能是这种颜色,也可能是其他颜色
//但其实并不影响结果: 如果拿的是该种颜色,那当然一点毛病没有。
// 即使拿到的不是该种颜色,我们可以把那几个“漏网之鱼”统计给拿出来的那写些颜色里。
// 因为我们本来就是要把所有颜色都拿出来的,所以并不影响。
count+=right[i];
}
else if(right[i]==0)
{
count+=left[i];
}
else
{
//走到这里时,就是排除了有0的情况了。
left_count+=left[i];
right_count+=right[i];
left_min=min(left_min,left[i]);
right_min = min(right_min,right[i]);
}
}
//需要的数据都统计完毕
// 去0拿出来的数量 保证拿出一只手的手套全部颜色至少一个, 另一边随便拿一只
return count + min(left_count - left_min + 1,right_count - right_min + 1) + 1;
}
};