哈希表
哈希表基础
哈希表的特点?
答案:
- 键值对存储
- 查找、插入、删除平均O(1)
- 空间换时间
- 可能有哈希冲突
Java中的哈希表
java
// HashMap
Map<String, Integer> map = new HashMap<>();
map.put("key", 1);
int value = map.get("key");
boolean exists = map.containsKey("key");
// HashSet
Set<Integer> set = new HashSet<>();
set.add(1);
boolean contains = set.contains(1);哈希表应用
两数之和(LeetCode 1)
答案:
java
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
return new int[0];
}字母异位词分组(LeetCode 49)
答案:
java
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] chars = str.toCharArray();
Arrays.sort(chars);
String key = new String(chars);
map.putIfAbsent(key, new ArrayList<>());
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}最长连续序列(LeetCode 128)
答案:
java
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int maxLength = 0;
for (int num : set) {
// 只从序列起点开始计数
if (!set.contains(num - 1)) {
int currentNum = num;
int currentLength = 1;
while (set.contains(currentNum + 1)) {
currentNum++;
currentLength++;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}无重复字符的最长子串(LeetCode 3)
答案:
java
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int maxLength = 0;
int left = 0;
for (int right = 0; right < s.length(); right++) {
char c = s.charAt(right);
if (map.containsKey(c)) {
left = Math.max(left, map.get(c) + 1);
}
map.put(c, right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}哈希表+前缀和
和为K的子数组(LeetCode 560)
答案:
java
public int subarraySum(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int count = 0;
int sum = 0;
for (int num : nums) {
sum += num;
if (map.containsKey(sum - k)) {
count += map.get(sum - k);
}
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
return count;
}连续数组(LeetCode 525)
答案:
java
public int findMaxLength(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
map.put(0, -1);
int maxLength = 0;
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i] == 1 ? 1 : -1;
if (map.containsKey(sum)) {
maxLength = Math.max(maxLength, i - map.get(sum));
} else {
map.put(sum, i);
}
}
return maxLength;
}LRU缓存
LRU缓存(LeetCode 146)
答案:
java
class LRUCache {
private Map<Integer, Node> map;
private int capacity;
private Node head, tail;
class Node {
int key, value;
Node prev, next;
Node(int key, int value) {
this.key = key;
this.value = value;
}
}
public LRUCache(int capacity) {
this.capacity = capacity;
this.map = new HashMap<>();
this.head = new Node(0, 0);
this.tail = new Node(0, 0);
head.next = tail;
tail.prev = head;
}
public int get(int key) {
if (!map.containsKey(key)) {
return -1;
}
Node node = map.get(key);
remove(node);
addToHead(node);
return node.value;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
Node node = map.get(key);
node.value = value;
remove(node);
addToHead(node);
} else {
if (map.size() == capacity) {
map.remove(tail.prev.key);
remove(tail.prev);
}
Node node = new Node(key, value);
map.put(key, node);
addToHead(node);
}
}
private void remove(Node node) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void addToHead(Node node) {
node.next = head.next;
node.prev = head;
head.next.prev = node;
head.next = node;
}
}练习题
- 有效的字母异位词(LeetCode 242)
- 两个数组的交集(LeetCode 349)
- 快乐数(LeetCode 202)
- 同构字符串(LeetCode 205)
- 前K个高频元素(LeetCode 347)