Two Sum(C语言实现)

本文介绍了使用哈希表以O(n)复杂度解决Two Sum问题的C语言实现方法,详细解析了算法思路,包括避免冲突和处理相同元素的策略,并提供了简洁的代码示例。
摘要由CSDN通过智能技术生成

Two Sum(C语言实现)

哈希(hash)表,亦称散列表,是通过函数映射的方式将关键字和存储位置建立联系,进而实现快速查找。

问题描述】给定一个整数数组 nums 和一个目标值 target,请给出该数组中和为目标值的两个元素的下标。
每组数组只需求出一种答案。
示例:
给定 nums = [7, 11, 2, 15], target = 9
因为 nums[0] + nums[2] = 7 + 2 = 9
所以返回 [0, 2]

算法实现】最简单的方法莫过于暴力求解,设计双重循环,直到找到问题的解,而双重循环对应的时间复杂度为O(n^2)。有没有可能降低其复杂度呢?

暴力求解的问题在于盲目遍历,如果我们提前将数组排好序,那么就可以有方向性的进行对比试探,直到找到问题的解。这种查找方式只需要一次循环就能实现,但常见的排序方式的复杂度也都较高。

有没有复杂度为O(n)的算法呢?

我们知道,通过映射方式建立的哈希表可以将查找的复杂度从O(n)降至O(1)。对于哈希表而言,最关键的两个问题是:如何设计散列函数,使得发生冲突的概率尽可能小;同时,如何处理好不可避免的冲突。

对于该问题,假设最小元素为min,那么,对于大于target-min的元素是不需要考虑的。若记max =target-min,我们可以建立一个长度为max-min+1的一维数组hash,就足以存放所有可能的元素。

算法实现
将数组中在[min, max]区间的元素从小到大存放在在hash表中,即hash[nums[i]-min]=num[i],表中空余部分填充-1作标记,表示无对应的nums元素。如下表所示:

那么,我们只需要一次循环,看下对应的hash[target-2×min-i]处是否有对应的nums元素即可,即判断hash[target-2×min-i]是否等于-1。如若不等于-1,则查找完毕,返回nums中对应的i+min和target-min+i的小标即可。
代码如下:

int* twoSum(int* nums, int numsSize, int target)
{
   
    int min = 2147483647;
    int i;
for (i = 0; i < numsSize; i++)
{
   
if (nums[i] < min)
            min = nums[i];
    }
    int max = target - min;
    int len = max - min + 1;   //确定hash长度
    int 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是三种不同的 C 语言实现 Two Sum 问题的方法: 方法 1:暴力枚举 这种方法的思路很简单,就是使用两个嵌套循环,枚举所有可能的组合,找到符合条件的组合。 ```c int* twoSum(int* nums, int numsSize, int target, int* returnSize){ int i, j; int *result = NULL; *returnSize = 0; result = (int*)malloc(2 * sizeof(int)); for(i = 0; i < numsSize - 1; i++){ for(j = i + 1; j < numsSize; j++){ if(nums[i] + nums[j] == target){ result[0] = i; result[1] = j; *returnSize = 2; return result; } } } return result; } ``` 方法 2:哈希表 这种方法使用哈希表来记录已经遍历过的数,在遍历到新的数时,检查哈希表中是否存在与之匹配的数。若存在,则找到了答案;若不存在,则将该数加入哈希表中。 ```c int* twoSum(int* nums, int numsSize, int target, int* returnSize){ int i; int *result = NULL; *returnSize = 0; result = (int*)malloc(2 * sizeof(int)); int hash[numsSize]; memset(hash, -1, sizeof(hash)); for(i = 0; i < numsSize; i++){ int numToFind = target - nums[i]; if(hash[numToFind] != -1){ result[0] = hash[numToFind]; result[1] = i; *returnSize = 2; return result; } hash[nums[i]] = i; } return result; } ``` 方法 3:排序+双指针 这种方法先将数组排序,然后使用双指针在已排好序的数组中查找符合条件的数对。 ```c int* twoSum(int* nums, int numsSize, int target, int* returnSize){ int i = 0, j = numsSize - 1; int *result = NULL; *returnSize = 0; result = (int*)malloc(2 * sizeof(int)); int *numsCopy = (int*)malloc(numsSize * sizeof(int)); memcpy(numsCopy, nums, numsSize * sizeof(int)); qsort(numsCopy, numsSize, sizeof(int), cmp); while(i < j){ if(numsCopy[i] + numsCopy[j] == target){ for(int k = 0; k < numsSize; k++){ if(nums[k] == numsCopy[i]){ result[0] = k; break; } } for(int k = numsSize - 1; k >= 0; k--){ if(nums[k] == numsCopy[j]){ result[1] = k; break; } } *returnSize = 2; break; } else if(numsCopy[i] + numsCopy[j] < target){ i++; } else{ j--; } } free(numsCopy); return result; } int cmp(const void *a, const void *b){ return *(int*)a - *(int*)b; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值