哈希表
本文描述了哈希表的基本概念,并给出了几道常见的算法题来帮助读者理解哈希表。
基本概念
哈希表实际上就是关联数组的抽象。具体来说,就是通过哈希函数将key映射到数组上,并保证每个key在数组中有一个唯一对应的索引。通常,这样会存在冲突问题,当发生位置冲突时,一般会进行重定位或者直接使用链表来解决冲突。
实战练习
/**
* @param {number[]} nums
* @return {number}
*/
var findRepeatNumber = function(nums) {
let dict=new Map();
let result=-1;
for(let item of nums){
if(dict.has(item)){
result=item;
break;
}
dict.set(item,1);
}
return result
};
/**题解
* 使用哈希表Map对象,当一个数已经在表里了,返回该数。
*/
/**
* @param {string} s
* @return {character}
*/
var firstUniqChar = function(s) {
if(s.length == 0){
return " ";
}
let map = new Map();
for(let str of s){
if(!map.has(str)){
map.set(str, 1);
}else{
map.set(str, 2);
}
}
for(let str of s){
let num = map.get(str);
if(num == 1){
return str;
}
}
return " ";
};
/**题解
* 先遍历一遍,得到每个数的计数,用数组中的值当做哈希表中的键,出现次数当值。
* 在从头到尾遍历一遍,当出现次数为1的值时,返回它。
*/
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let max_subLen = 0, cur_subLen = 0, map = new Map();
for(let i = 0, len = s.length; i < len; i++){
if(!map.has(s[i]) || i - map.get(s[i]) > cur_subLen){
cur_subLen++;
map.set(s[i], i);
if(i == len - 1 && max_subLen < cur_subLen){
max_subLen = cur_subLen;
}
}else{
let preIndex = map.get(s[i]);
if(i - preIndex > cur_subLen + 1 && max_subLen < cur_subLen + 1){
max_subLen = cur_subLen + 1;
}else if(i - preIndex <= cur_subLen + 1 && max_subLen < cur_subLen){
max_subLen = cur_subLen;
}
cur_subLen = i - preIndex;
map.set(s[i], i);
}
}
return max_subLen;
};
/**题解
* 滑动窗口算法:当新的字符不在滑动窗口时,直接添加;当在滑动窗口时,从前一个重复的字符位置后一位创建新的滑动窗口,并和之前的滑动窗口对比长度,以更新最大长度。
* 该解答使用了哈希表,实际上直接使用String对象的indexOf方法会简单得多。
*/
总结
哈希表的键查值效率很高,善于使用哈希表能显著降低时间复杂度。