[LeetCode刷题笔记(C语言)] 01 - Two Sum

原题链接: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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值