题目
题解
typedef struct {
int key;
int num;
UT_hash_handle hh;
} HashNode, *HashTable;
int countPairs(int* deliciousness, int deliciousnessSize){
//预设结果,2的幂次
int result[22];
for(int i = 0; i < 22; i++){
if(i == 0){
result[i] = 1;
}else {
result[i] = result[i-1]*2;
}
}
//创建哈希表将所有元素存进哈希表中
HashTable ht = NULL;
for(int i = 0; i < deliciousnessSize; i++){
HashNode * temp = NULL;
HASH_FIND_INT(ht,&deliciousness[i],temp);
if(temp == NULL){
temp = (HashNode*)malloc(sizeof(HashNode));
temp->key = deliciousness[i];
temp->num = 1;
HASH_ADD_INT(ht,key,temp);
}else{
temp->num += 1;
}
}
//遍历数组
long count = 0;
for(int i = 0; i < deliciousnessSize; i++){
for(int j = 0; j < 22; j++){
int target = result[j] - deliciousness[i];
HashNode * temp = NULL;
HASH_FIND_INT(ht,&target,temp);
if(temp != NULL){
if(temp->key != deliciousness[i]){
//count = (count + temp->num) % 1000000007;
count += temp->num;
}else{
//count = (count + temp->num - 1) % 1000000007;
count += temp->num - 1;
}
}
}
}
//最后要除以2
count = count / 2;
count %= 1000000007;
return count;
}
心得
最近遇到很多问题,又有了一点经验和做算法题的思路。
看到一个题目:
首先应该考虑输入与输出,思考数的范围。
其次思考算法。
然后再思考算法中使用到的数据结构。
本题要点
首先看到给的数据个数10^5数量级,然后再看数据范围0~2^20。
思考算法:如果使用双循环的话时间复杂度是10^10,大概率会超时。可以使用哈希表来做,现将所有的元素存入哈希表中,再依次遍历每个元素寻找是否有另一个元素与本元素之和是2的幂次。
哈希表的结构应包含键值与键值出现的个数。
其他细节①:2的幂次可以事先存储在一个数组中,从数据范围可以得知,最小的2的幂次是2^0=1,最大的幂次是2^20+2^20=2^21。因此设置一个大小为22的数组result,将result[0]设置为1,后续遍历result[i]=result[i-1]*2即可得到所有的2的幂次。
其他细节②:在计算结果时,并不是加上一个数就对1000000007取余,不然可能中间结果值刚超过1000000007就取余了然后后面就乱了....,而是要最后所有次数都加上之后再进行取余。