“哈希表” 考察频率很高!
哈希是典型的以空间换时间的数据结构,它的插入/删除/查找的时间复杂度都是 O(1)。而空间复杂度则取决于存储的数据。例如有M个键,那么可以达到 O(M) 的空间复杂度。??
3. 无重复字符的最长子串:滑动窗口 + 重复值在窗口内判断
要求一次遍历!是频率最高的题目。
- 用双指针
left
和i
维护滑动窗口,用来保存无重复字符的子串。 - 哈希表保存 {字符 :对应下标},注意判断重复值是否在窗口内(大于等于)!
const lengthOfLongestSubstring = (s) => {
const map = new Map();
let maxLength = 0; // 最长子串的长度
let left = 0; // 滑动窗口左边界
for (let i = 0; i < s.length; i++) {
if (map.has(s[i]) && map.get(s[i]) >= left) { // 重复字符的索引大于或等于左指针
left = map.get(s[i]) + 1; // 举例就能理解
}
maxLength = Math.max(maxLength, i - left + 1);
map.set(s[i], i);
}
return maxLength;
}
时间复杂度:O(n)。哈希表插入和搜索的时间复杂度O(1)。
空间复杂度:O(m)。m 是哈希存储键的个数,最多是字符串s的大小。
1. 两数之和
创建哈希表保存 {元素:元素下标} 。遍历数组判断哈希表中是否有等于target - nums[i]
的值,如果有则返回两个下标,否则就更新哈希表。
const twoSum = (nums, target) => {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
if (map.has(target - nums[i])) {
return [map.get(target - nums[i]), i];
} else {
map.set(nums[i], i);
}
}
};
时间复杂度:O(n)。
空间复杂度:O(n)。主要是哈希表的开销
349. 两个数组的交集:Set
- 借助
Set
去重,因为Set
的成员值是唯一不重复的。 - 优化点:遍历长度较小的集合。
const intersection = (nums1, nums2) => {
const set1 = new Set(nums1); // [...set]
const set2 = new Set(nums2);
const res = [];
// if (set1.size > set2.size) { // 遍历较小的集合
// [set1, set2] = [set2, set1];
// }
for (let item of set1) {
if (set2.has(item)) {
res.push(item);
}
}
return res;
};
时间复杂度:O(m + n)。其中两个new Set
储存两个数组中的元素需要 O(m + n) 的时间,然后遍历较小的集合并进行判断需要 O(min(m, n)),因此总时间复杂度是 O(m + n)。
空间复杂度:O(m + n)。主要取决于两个 set 集合。