上题。。。
基础思想:一开始看到题,很多人都会灵光一现,这不是数学里面组合问题嘛,只需要将数组中的数据两两组合,相加比对,就能找出答案。用代码实现无非是一个嵌套for循环的事。
复杂度考察:先固定第一个数,依次与后面n-1个数组合,再固定第二个数,与后面n-2个数组合...最后一个固定的是倒数第二个数,与最后一个数组合。因此复杂度为(n-1)+(n-2)+...1=n(n-1)/2=
On^2。
升维思想:刚刚是在数组里找两个组合数比对其和与target,何不让target减去其中一个数,在数组中找有没有匹配的另一个数呢?
查找表法
查表法指的是先将一些计算好的数据存在一个长量数组中,需要时直接调用。比如创建一个哈希表,根据key直接查找其value
此题中数组元素的值就是key,索引就是value。从第一个数开始算出another=target-nums[0],查找哈希表中有无another。没有就继续,有就直接返回目前索引值和another对应哈希表中的value。
复杂度:最多需要做减法n次,查找n次,所以复杂度为On,明显小于基础算法
代码解析
struct hashTable {
int key;
int val;
UT_hash_handle hh; //hh是内部使用的hash处理句柄,在使用 过程中,只需要在结构体中定义一个 UT_hash_handle类型的变量即可,不需 要为该句柄变量赋值,但必须在该结构体 中定义该变量。
}; //创建哈希表数据类型
struct hashTable* hashtable; //创建哈希表结构指针变量(全局)
struct hashTable* find(int ikey) { //实现查找接口的函数
struct hashTable* tmp; 需要先定义一个哈希类型的指针
HASH_FIND_INT(hashtable, &ikey, tmp); 用HASH_FIND_INT()函数直接查找,如 果有匹配对象将对象复制给刚才定义的指针
return tmp;
}
void insert(int ikey, int ival) {
struct hashTable* it = find(ikey); //如果有匹配对象,返回对象的指针,否则返回NULL (it为接口指针)
if (it == NULL) {
struct hashTable* tmp = malloc(sizeof(struct hashTable));
tmp->key = ikey, tmp->val = ival;
HASH_ADD_INT(hashtable, key, tmp);
} else { //没有匹配,将其插入哈希表
it->val = ival;
}
}
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
hashtable = NULL;
for (int i = 0; i < numsSize; i++) {
struct hashTable* it = find(target - nums[i]);
if (it != NULL) {
int* ret = malloc(sizeof(int) * 2);
ret[0] = it->val, ret[1] = i;
*returnSize = 2;
return ret; //第一个出口,成功
}
insert(nums[i], i);
}
*returnSize = 0;
return NULL; //第二个出口,失败
}
代码作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/two-sum/solution/liang-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
附上一个自己为了更直观地理清思路画的不规范的流程图