题目描述:
给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
注意: 数组的长度为[2, 10,000],并且确定为偶数。数组中数字的大小在范围[-100,000, 100,000]内。
解法:
设总糖果数为 m,其中不同的糖果种类为 n, 所求结果为 x。
一方面,妹妹分到的糖果最多不超过总糖果数的一半,即 。
另一方面,如果 n >= m / 2,则妹妹最多分到 m / 2 种糖果;如果 n < m / 2,则最多分到 n 种不同的糖果。
综上所述, x = min(m / 2 , n )。
其中 m / 2 比较好求,关键是求出 n 的值。如果直接遍历每一个数,并与其他数比较,时间复杂度将会达到 o(n^2),将会超时。在各种高级编程语言中的 set 类底层采用 哈希表、红黑树等高级数据结构,可以在 o(n*log2(n)) 的时间复杂度完成去重操作。
在这道题中,我们可以合理利用数组中的数据大小在 [-100000, 100000] 中的特性,构造没有哈希冲突的“哈希表”,直接将数值作为哈希值,映射到长度为 200001 数组中,将对应的位变为1,然后统计1的出现次数,即可得到 n ,可以算出这种方式的时间复杂度为 o(n)!
结果和代码如下,可以看到性能还是不错的。
int distributeCandies(int* candyType, int candyTypeSize){
char hash_table[200001] = {0};
int i;
int max = candyTypeSize / 2;
for(i=0; i<candyTypeSize; i++)
hash_table[candyType[i] + 100000] = 1;
int count = 0;
for(i=0; i<200001; i++){
if(hash_table[i])
count ++;
if(count == max)
break;
}
return count;
}