原题链接:Two Sum
题目原文:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
|ू・ω・` )
大体意思是给你一个数组nums以及一个数字target,要从数组中找出和为target的两个数,并以数组的形式返回。
第一种方法,刚开始码题的人都知道,没有什么是循环解决不了的,如果有,那就多套几层, 同理这道题也是双层循环可以解决的,简单遍历两遍数组,时间复杂度为O(n²),运行速度超过0.8%的用户 。当然可以进行一些优化,加一些判断语句避免不必要的搜索,速度也可以很快。
然后第二种种方法hash map,时间复杂度为O(n)。
哈希数组要初始化
哈希数组要初始化
哈希数组要初始化
为了避免不必要的搜索,我们首先要确定数组nums中有效数字的范围。什么算有效的数字呢?在一个有很多数的数组nums中,假设其中最小的数字min正好是和为target的两个加数之一,那么显然另一个数字(target-min)如果恰好在数组中存在的话,必为所有符合条件的加数中最大的一个数,因此我们把它称作max。下面我们看一个简单的式子:
C - a = b
在减法运算中,减数与差的大小成反比关系,当C = target, a = min时,对应的b(max)必然为数组中所有产生和为target的加数中的最大值。因此我们确定在数组nums中,满足条件的加数必定都小于max。满足以上条件的数字,我们把它定义为有效的。接着,为了节省空间,我们还可以这么干:既然已经确定最小值以及有效数字的范围,我们可以进一步确定有效数字与min的差的范围,并把这些差作为hash map的下标,因此hash map的大小为:len = max - min + 1。那hash map里存什么呢?存当前元素在nums的下标。也就是说,nums[i]这个元素本身作为信息存在hash map第nums[i] - min的位置。如何确定与之对应的另一个加数也在数组中呢?假设当前元素为y,那么:
target - x = y <=> target - x - min = y - min
因此我们遍历一遍nums,若当前元素nums[i] = y是有效元素,则判断hash[(target - y - min)]是否为初始值,如果不是,那么这两个加数就找到了。回过来,在判断hash这步结束之后,如果另一个加数尚为出现,那对应的hash应该还是一个初始值,这时候我们把nums的信息存进去,这样另一个加数出现后才可以判断它的同伴出现过。
具体实现如下:
#define MIN_NUM 2147483647
int* twoSum(int* nums, int numsSize, int target) {
int min = MIN_NUM;
int max; // 满足条件的最大值
int i;
int len; // 哈希表长,即max与min之间的差值
for (i = 0; i < numsSize; i++) {
min = (min < nums[i]) ? min : nums[i];
}
max = target - min;
len = max - min + 1; // 两元素差的最大范围
int *hash = (int*)malloc(len * sizeof(int)); // 哈希表,存第i个元素与min的差
int *ans = (int*)malloc(2 * sizeof(int)); // 最后的数组
int *P_hash = hash;
int *n = nums;
for (i = 0; i < len; i++) {
hash[i] = -1;
}
for (i = 0; i < numsSize; i++) {
if ((*(n + i) - min) < len) { //对符合条件的元素进行判断,对于num[i],将其与min的差值作为下标,将其地址存在hash中
if (*(P_hash + target - (*(n + i) + min)) != -1) { // 满足条件时,target - y - min = x - min <-> x+y = target;
ans[0] = *(P_hash + target - (*(n + i) + min));
ans[1] = i;
return ans;
}
hash[*(n + i) - min] = i;
}
}
free(hash);
return ans;
}