(一)LRU (Least Recently Used) cache
https://leetcode.com/problems/lru-cache/description/
题目:为LRU缓存策略设计一个数据结构,它应该支持以下操作:获取数据(get)和写入数据(set)。
获取数据get(key):如果缓存中存在key,则获取其数据值,否则返回-1。
写入数据set(key, value):如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
解答:在使用hashMap存储的同时,将key用链表结构表示,链表从头到尾代表由新到旧的顺序:
对于get操作,需要更新链表最新的节点位置;
对于set操作,更新链表最新位置,若缓存达上限,则将链表尾部的key元素从hashMap中删除;
第一次犯错:对于重复的key值,直接在链表头部添加key值,忘记删除原有的值;
代码:
class LRUCache {
private class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
this.next = null;
}
}
Map<Integer, Integer> hashMap;
List<ListNode> list;
int size;
ListNode dummy = new ListNode(0);
public LRUCache(int capacity) {
hashMap = new HashMap<>();
list = new LinkedList<>();
size = capacity;
}
public int get(int key) {
if (hashMap.containsKey(key)) {
deleteOld(key);
addNew(key);
return hashMap.get(key);
} else {
return -1;
}
}
public void put(int key, int value) {
if (hashMap.containsKey(key)) {
deleteOld(key);
}
addNew(key);
if (hashMap.containsKey(key) || hashMap.size() < size) {
hashMap.put(key, value);
} else {
ListNode tail = dummy.next;
for (int i = 0; i < size; i++) {
tail = tail.next;
}
hashMap.remove(tail.val);
hashMap.put(key, value);
}
}
private void deleteOld (int key) {
ListNode find = dummy.next;
ListNode findPrev = dummy;
while (find.val != key) {
find = find.next;
findPrev = findPrev.next;
}
findPrev.next = find.next;
}
private void addNew (int key) {
ListNode temp = dummy.next;
ListNode node = new ListNode(key);
dummy.next = node;
node.next = temp;
}
}
(二)Group Anagrams
题目:给一字符串数组, 将错位词(指相同字符不同排列的字符串) 分组
解答:将字符串按照字母顺序排列后的字符串作为key, value值为一个ArrayList, 将未排序字符串根据key值添加到对应的ArrayList中;
代码:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String s : strs) {
char[] word = s.toCharArray();
Arrays.sort(word);
String key = String.valueOf(word);
if (map.containsKey(key)) {
map.get(key).add(s);
} else {
map.put(key, new ArrayList<>());
map.get(key).add(s);
}
}
return new ArrayList<>(map.values());
}
}
(三)Longest Consecutive Sequence
题目:给定一个未排序的整数数组,找出最长连续序列的长度,要求时间复杂度为O(n);
解答:先将全部的数放入hashSet中,依次遍历数组中元素。在每次循环中,找到当前元素在hashSet中存在的相邻最小和最大元素,在找最小最大的过程中,若找到则将该元素
删除(避免重复查找),每次更新最长的元素长度;
代码:
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
int res = 0;
for (int i = 0; i < nums.length; i++) {
set.add(nums[i]);
}
for (int i = 0; i < nums.length; i++) {
int small = nums[i] - 1;
int big = nums[i] + 1;
while (set.contains(small)) {
set.remove(small--);
}
while (set.contains(big)) {
set.remove(big++);
}
res = Math.max(res, big - small - 1);
}
return res;
}
}