题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
暴力法:
两次for循环,找出满足nums[i] + nums[j]=target;的下标i和j
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int *result=NULL;
returnSize=2;
for(int i=0;i<numsSize-1;i++){
for(int j=i+1;j<numsSize;j++){
if(nums[i]+nums[j]==target){
result = (int)malloc(sizeof(int) * 2);
result[0]=i;
result[1]=j;
return result;
}
}
}
return result;
}
哈希表:
- 记录的存储位置与关键字之间存在对应关系,Loc(i)=H(keyi)
- 查找速度极快O(1),查找效率与元素个数n无关
- 选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;
- 查找时,由同一个函数对给定值k计算地址,将k与地址单元中元素关键码进行比,确定查找是否成功。
哈希函数常用除留取余法:
取关键字被某个不大于哈希表长度m的数p除后的余数作为哈希地址,即:
Hash(key)=key mod p (p ≤ m)
如何选取合适的p?
设表长为m,取p≤m且为质数
冲突:不同的关键码映射到同一个哈希地址
常用解决办法:用线性探测再散列处理冲突
新位置Hi=(Hash(key)+di) mod m ( 1≤i < m )
其中:m为哈希表长度
di 为增量序列 1,2,…m-1,且di=i
int hash(int key, int modnum) {
int re = key % modnum;//存储在的哈希表位置返回值
if (re < 0) re = re + mod;
return re;
}
int *twoSum(int *nums, int numsSize, int target, int *returnSize) {
int *ret = (int *)malloc(2 * sizeof(int));//return用
int modnum = numsSize * 2 - 1;//一般num设为<=哈希表长,且为质数
int *hashtable = (int *)malloc(mod * sizeof(int));//哈希表
int *tag = (int *)malloc(mod * sizeof(int));//哈希表此位置是否为空,空0满1
int i, j, index, temp;
for (i = 0; i < mod; i++) tag[i] = 0;
for (i = 0; i < numsSize-1; i++) {
temp = target - nums[i];
index = hash(temp, mod);//第一个加数位于哈希表的位置
while (tag[index] == 1) {
if (hashtable[index] == temp) {
for (j = i+1; nums[j] != temp; j++);
ret[0] = j;ret[1] = i;
*returnSize = 2;// for leetcode
free(hashtable);free(tag);
return ret;
}
index = (index + 1) % mod;//处理冲突
}
index = hash(nums[i], mod);//第二个加数位于哈希表的位置
while (tag[index] == 1) index = (index + 1) % mod;
hashtable[index] = nums[i];
tag[index] = 1;
}
*returnSize = 0;
free(hashtable);free(tag);
return ret;
}