解题思路
我们的目的是要求出最少一共拿多少只手套,才可以保证至少有一对配对的手套。我们可以考虑左右手套分开拿。
- 如果某种颜色的手套没有对应配对的另外一只手套的话,为了防止最差情况即:最终全拿到的是这样颜色手套。那就保证至少要把这些数量的手套拿走,其效果相当于以选代ban。
代码:if( left[i] * right[i] == 0) sumBare++;
- 接下来我们可以假设剩下这样的场景:剩下颜色的手套,左右手至少都有一只可以配对。我们分别记录剩下的左、右手的手套数量的总和,及其每只手中最少数量的大小。首先保证其中一只手的所有颜色都能拿到,且数量最少的颜色只拿一只,这样就做到了以最少的数量,拿到其中一只手的所有颜色的手套,接下来只需在另外一只手的手套里随便拿一只即可。
代码:min( sumLeft - minleft + 1, sumRight -minRight + 1) + 1;
- 最后加上第一步中没有配对的,仅有一只手的手套数量的总和,就是最终返回的结果。
return sumBare + min( sumLeft - minleft + 1, sumRight -minRight + 1) + 1;
代码实现
public:
int findMinimum(int n, vector<int> left, vector<int> right)
{
// 分别记录左右手中数量最少的手套的数量
int minLeft = INT_MAX;
int minRight = INT_MAX;
// 分别记录左右手都有的某种颜色的手套数量的总和
int sumLeft = 0;
int sumRight = 0;
// 合并记录左右手中没有配对颜色的手套的数量
int sumBare = 0;
// 根据下标对应的颜色同时遍历上面两个数组,完成上面定义变量的统计
for(int i = 0; i < n; ++i)
{
if(left[i]*right[i] == 0)
{
sumBare += left[i]+right[i];
}
else
{
sumLeft += left[i];
sumRight += right[i];
minLeft = min(minLeft, left[i]);
minRight = min(minRight, right[i]);
}
}
// 最终结果返回
return sumBare + min(sumLeft - minLeft + 1, sumRight - minRight + 1) +1;
}
};
性能分析
- 时间复杂度:O(n)。两个长度相同的数组同时遍历一遍。
- 空间复杂度:O(1)。