LEETCODE的第一题——两数之和(哈希表)
本文主要用于记录刷力扣的题解,,因为自己算法太菜,所以想通过深度学习力扣的每一道题目的原理来提高自己。
下面内容为自己学习时的记录,如有错误,欢迎指正🍭
一、 题目——1.两数之和
二、 题解一:暴力解法
最先想到的就是使用for循环直接遍历数组,C语言代码如下👇
int *twoSum(int *nums,int numsize,int target, int *returnSize){
for (int i= 0 ;i<numsize ; i++){
for(int j =i+1;j<numsize ; j++)
{if(num[i]+num[j]==target){ //如果找到有两数之和等于目标值,则找到了
int* ret =malloc(sizeof(int)*2);//创建空间
ret[0]=i;
ret[1]=j;
*returnSize = 2;
return ret;
}
}
}
*returnSize = 0;
return NULL;//没找到返回NULL
}
三、 题解二:哈希表
进阶:你可以想出一个时间复杂度小于 O(n^2) 的算法吗?
看到这个进阶我就知道这个题目不简单,后来看到官方是使用哈希表进行的优化
发现使用纯C是无法快速的使用一些数据结构的算法的(比如这题的哈希表,建立一个哈希表的代码真的很长),所以我后来使用python
复现了一下(相比于其他语言,目前就python于我而言更加熟悉)后面有时间的话一定要去学习C++!!!
3.1 哈希表(Hash Table)原理
哈希表是一种常见的数据结构,它用于存储键值对
(Key-Value pairs)
并提供高效的数据查找、插入和删除操作。其核心原理是散列函数(Hash Function)。
基本原理
散列函数
:哈希表使用散列函数将键(key)映射为一个索引,这个索引用来在内部数组中存储值(value)。这个映射是关键,因为它决定了如何将键分布到数组的不同位置。数组存储
:哈希表内部通常包含一个固定大小的数组,每一个数组元素被称为“桶”(Bucket)或“槽”(Slot)。这些桶用来存储键值对。散列函数的输出确定了键值对应存储在哪个桶里。处理冲突
:由于不同的键可能映射到相同的索引,所以冲突是不可避免的。哈希表必须能够有效地处理冲突。常见的处理冲突的方法包括链表法(将多个键对存储在同一个桶中,并使用链表来管理他们)和开放地址法(在冲突时寻找下一个可用的桶)等。常见操作
:哈希表支持以下常见操作:
插入(Insertion):将新的键值对插入到哈希表中。首先通过散列函数计算键的索引,然后将值存储在对应的桶中。
查找(Lookup):根据给定的键查找对应的值。通过散列函数计算索引,然后在相应的桶中查找值。
删除(Deletion):根据给定的键删除对应的值。通过散列函数计算索引,然后从相应的桶中删除值。- 性能分析:在理想情况下,良好设计的哈希表可以提供常数时间的平均复杂度(O(1))来执行上述操作。但是,如果哈希表的散列函数不均匀或者桶的数量不足,性能可能会下降,导致冲突增多,使得操作的时间复杂度变为O(n)。
3.2 C语言解题
//自定义一个结构体,用来表示哈希表中的每一个元素,成员包括两个整数成员`key`和`val`分别表示键和值。
struct hashTable{
int key;
int val;
UT_hash_handle hh;//特殊的宏,对象的名称是hh
}
struct hashTable* hashtable;//声明一个名为hashtable的指针变量,该指针可以用来指向 struct hashTable 类型的对象
//声明了一个名为 find 的函数,该函数接受一个整数参数 ikey,并返回一个指向 struct hashTable 类型对象的指针
struct hashTable* find(int ikey){
struct hashTable* tmp;
HASH_FIND_INT(hashtable,&ikey,tmp);//使用了 "uthash" 库提供的 HASH_FIND_INT 宏来查找哈希表中是否存在具有指定整数键 ikey 的元素
return tmp;
}
//向哈希表中插入新的元素
void insert(int ikey,int ival){
struct hashTable* it =find(ikey);//调用 find 函数来检查是否已存在具有相同的键
if(it==NULL){//不存在
struct hashTable* tmp = malloc(sizeof(struct hashTable));//创建一个新的 hashTable 结构体
tmp->key =ikey;
tmp->val =ival;
HASH_ADD_INT(hashtable,key,tmp);//HASH_ADD_INT 宏将其添加到哈希表
}
else{//如果已存在具有相同'键'的元素,它将更新该元素的值。
it->val=ival;
}
}
//具体实现函数
int* twoSum(int*nums,int numSize, int target, int* returnSize){
hashtable = NULL;
for (int i=0;i<numSize;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;
}
利用 “uthash” 库来实现哈希表,通过自定义的结构体和一些宏来操作哈希表中的元素
3.3 python 解题
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict() #创建一个空的字典(哈希表)hashtable,用于存储整数与其索引之间的映射关系
for i, num in enumerate(nums): #元素值 num 和索引 i
if target - num in hashtable:
return [hashtable[target - num], i]#hashtable[target - num] 表示之前已经存储在哈希表中的整数的索引,i 表示当前遍历的整数的索引
hashtable[nums[i]] = i #nums[i] 作为键,索引 i 作为值存储
return []
使用字典(哈希表)来解决两数之和的问题。它遍历整数列表,查找是否存在两个元素的和等于目标值,并返回这两个元素的索引。如果没有找到匹配,返回一个空列表。这种方法的时间复杂度为
O(n)
,其中n是列表的大小。
可以很直观的看出来python的代码比c语言简练很多/(ㄒoㄒ)/~~
写在最后:
1.不要想着纯C编程,最好同时熟练使用C和C++,如果有机会的话可以在多掌握一门语言,以后机试的时候可能会用到
2.一定要早一点开始练习算法!!还有要坚持!!