本篇博客解析 001-twoSum。
一、题目
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.
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:给定 nums = [2, 7, 11, 15], target = 9。因为 nums[0] + nums[1] = 2 + 7 = 9,所以返回 [0, 1]。
二、分析
1. 先将数组由小到大排序(新建一个结构体,用于保存下标和数据)。
2. 新建变量 head 和 tail,从数组的头和尾开始,向中间取数据。用 target 减去 head,如果 diff 比 tail 大,说明需要将 head 后移。如果 diff 比 tail 小,说明需要将 tail 前移。如果 diff 和 tail 相等,即为满足条件的解。
3. 在移动变量时,要注意数组中同一个元素不能使用两遍,所以 head 和 tail 不能指向相同元素。且如果两个相邻元素的数据相等,则移动后结果和上次相同,应继续移动,不需要再次进入循环判断。
三、背景知识
在本题代码中,涉及排序操作。我没有自己实现,而是直接调用了 qsort。关于 qsort 的详细描述,可参照《【C语言库函数】-qsort》。
四、代码
1 /* 2 * 新建结构体,记录nums中每个元素的下标和数据,以便排序处理 3 */ 4 typedef struct Object 5 { 6 int index; 7 int value; 8 } Object; 9 10 /* 11 * 用于 qsort 12 */ 13 int compare(const void *objA, const void *objB) 14 { 15 return (((Object *)objA)->value - ((Object *)objB)->value); 16 } 17 18 int* twoSum(int* nums, int numsSize, int target, int* returnSize) 19 { 20 int i = 0, j = 0; 21 Object *objs = NULL; 22 int *result = NULL; 23 24 // 合法性检查 25 if (!nums || numsSize < 2) 26 return NULL; 27 28 // 为 objs 分配空间,用于存储 nums 中各元素的下标和数据 29 objs = malloc(sizeof(Object) * numsSize); 30 31 // 为 result 分配空间,用于存储结果 32 result = malloc(sizeof(int) * 2); 33 34 *returnSize = 2; 35 36 // 将nums中的元素写入objs 37 for (i = 0 ; i < numsSize ; i++) 38 { 39 objs[i].index = i; 40 objs[i].value = nums[i]; 41 } 42 43 // 将 objs 按从小到大顺序排序 44 qsort(objs, numsSize, sizeof(Object), compare); 45 46 // i 指向 objs 首部元素 47 i = 0; 48 49 // j 指向 objs 尾部元素 50 j = numsSize - 1; 51 52 // 由于每个元素只能用一次,所以限制条件为 i < j 53 while (i < j) 54 { 55 int diff = target - objs[i].value; 56 57 if (diff < objs[j].value) 58 while (--j > i && objs[j].value == objs[j+1].value) ; 59 else if (diff > objs[j].value) 60 while (++i < j && objs[i].value == objs[i-1].value) ; 61 else 62 { 63 result[0] = objs[i].index; 64 result[1] = objs[j].index; 65 66 return result; 67 } 68 } 69 70 return NULL; 71 }