我们最后用 Java 的内置类型 LinkedHashMap 来实现 LRU 算法,逻辑和之前完全一致,我就不过多解释了:
class LRUCache {
int cap;
LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.cap = capacity;
}
public int get(int key) {
if (!cache.containsKey(key)) {
return -1;
}
// 将 key 变为最近使用
makeRecently(key);
return cache.get(key);
}
public void put(int key, int val) {
if (cache.containsKey(key)) {
// 修改 key 的值
cache.put(key, val);
// 将 key 变为最近使用
makeRecently(key);
return;
}
if (cache.size() >= this.cap) {
// 链表头部就是最久未使用的 key
int oldestKey = cache.keySet().iterator().next();
cache.remove(oldestKey);
}
// 将新的 key 添加链表尾部
cache.put(key, val);
}
private void makeRecently(int key) {
int val = cache.get(key);
// 删除 key,重新插入到队尾
cache.remove(key);
cache.put(key, val);
}
}
3.11 秀操作之 k 个一组反转链表
本文对应的力扣题目:
25.K个一组翻转链表
ListNode reverseKGroup(ListNode head, int k) {
if (head == null) return null;
// 区间 [a, b) 包含 k 个待反转元素
ListNode a, b;
a = b = head;
for (int i = 0; i < k; i++) {
// 不足 k 个,不需要反转,base case
if (b == null) return head;
b = b.next;
}
// 反转前 k 个元素
ListNode newHead = reverse(a, b);
// 递归反转后续链表并连接起来
a.next = reverseKGroup(b, k);
return newHead;
}
/** 反转区间 [a, b) 的元素,注意是左闭右开 */
ListNode reverse(ListNode a, ListNode b) {
ListNode pre, cur, nxt;
pre = null; cur = a; nxt = a;
// while 终止的条件改一下就行了
while (cur != b) {
nxt = cur.next;
cur.next = pre;
pre = cur;
cur = nxt;
}
// 返回反转后的头结点
return pre;
}
5.6 如何寻找最长回文子串
5.最长回文子串
string longestPalindrome(string s) {
string res;
for (int i = 0; i < s.size(); i++) {
// 寻找长度为基数的回文子串
string s1 = palindrome(s, i, i);
// 寻找长度为偶数的回文子串
string s2 = palindrome(s, i, i + 1);
// res = longest(res, s1, s2)
res = res.size() > s1.size() ? res : s1;
res = res.size() > s2.size() ? res : s2;
}
return res;
}
// 从 s[l] 和 s[r] 开始向两端扩散
// 返回以 s[l] 和 s[r] 为中心的最长回文串
string palindrome(string& s, int l, int r) {
// 防止索引越界
while (l >= 0 && r < s.size() && s[l] == s[r]) {
l--; r++;
}
return s.substr(l + 1, r - l - 1);
}
2.15 经典动态规划:0-1 背包问题
2.15.1 动规标准套路
int knapsack(int W, int N, vector<int>& wt, vector<int>& val) {
// base case 已初始化
vector<vector<int>> dp(N + 1, vector<int>(W + 1, 0));
for (int i = 1; i <= N; i++) {
for (int w = 1; w <= W; w++) {
if (w - wt[i-1] < 0) {
// 背包容量不够了,这种情况下只能选择不装入背包
dp[i][w] = dp[i - 1][w];
} else {
// 装入或者不装入背包,择优
dp[i][w] = max(dp[i - 1][w - wt[i-1]] + val[i-1],
dp[i - 1][w]);
}
}
}
return dp[N][W];
}
//斐波那契
public static int fib(int n){
if(n == 0){return 0;}
if(n == 1 || n == 2){return 1;}
int pre = 1,cur = 1;
for(int i=3;i<=n;i++){
int sum = pre+cur;
pre = cur;
cur=sum;
}
return cur;
}