问题背景:leetcode第一题“两数之和”
最容易想到的方法当然是暴力法了,直接上代码
var twoSum = function(nums, target) {
var result = new Array();
for (var i = 0; i < nums.length; i++) {
for (var m = i+1; m < nums.length ; m++) {
if (target - nums[i] == nums[m]) {
result.push(i);
result.push(m);
break;
}
}
}
return result;
};
当然我也知道这绝对不是效率最高的方法,在看过别人解答后,我了解到了这种结构:哈希表(Hash table)
哈希表
定义:哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。
根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度,Hash Table的查询速度非常的快,几乎是O(1)的时间复杂度
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
联系到本题目,想到可以建立一个f(x)=target - nums[i]为存在函数的哈希表
function makeHash(nums, target){
for( let i = 0 ; i < nums.length ; i++){
myHashTable.push(target - nums[i])
}
}
var twoSum = function(nums, target) {
makeHash(nums, target);
for(let i = 0 ;i <nums.length ; i++){
if (myHashTable.indexOf(nums[i])!=null && myHashTable.indexOf(nums[i])!=i) {
result.push(i);
result.push(myHashTable.indexOf(nums[i]));
break;
}
}
console.log(result)
return result;
};
let nums = [3,2,4];
let target = 6;
输出正确
哈希冲突
定义:不同的关键字经过散列函数的计算得到了相同的散列地址。比如字典中存在同音字
解决方法:常用的方法是链地址法
百度来这张图片来说明结构
继续拿字典为例,应对同音字的存在,我们可以专门为他们建立一个区域来存放这些字。链地址就是这样,为符合函数的不同值单独开辟处一个空间(链表)来储存数据。