LRU 最近最少(最久)未使用
剑指 Offer II 031. 最近最少使用缓存 - 力扣(Leetcode)
需要能1 快速定位 2 快速删除 hash表+双向链表
LinkedHashMap
496. 下一个更大元素 I - 力扣(Leetcode)
单调栈
239. 滑动窗口最大值 - 力扣(Leetcode)
单调队列
思路就是每次在插入的时候,删除前面小于自己的值,来保证队列是递减的
需要从头和尾进行插入删除,LinkedList<Integer> getLast pollLast addLast
面试题59 - II. 队列的最大值 - 力扣(Leetcode)
剑指 Offer II 059. 数据流的第 K 大数值 - 力扣(Leetcode)
手写二叉堆
思路:用数组来模拟完全二叉树,关建是上浮(swim)和下沉(sink)指定节点倒关建位置的函数
public class MaxPQ
<Key extends Comparable<Key>> {
// 存储元素的数组
private Key[] pq;
// 当前 Priority Queue 中的元素个数
private int size = 0;
public MaxPQ(int cap) {
// 索引 0 不用,所以多分配一个空间
pq = (Key[]) new Comparable[cap + 1];
}
/* 返回当前队列中最大元素 */
public Key max() {
return pq[1];
}
/* 插入元素 e */
public void insert(Key e) {
size++;
// 先把新元素加到最后
pq[size] = e;
// 然后让它上浮到正确的位置
swim(size);
}
/* 删除并返回当前队列中最大元素 */
public Key delMax() {
// 最大堆的堆顶就是最大元素
Key max = pq[1];
// 把这个最大元素换到最后,删除之
swap(1, size);
pq[size] = null;
size--;
// 让 pq[1] 下沉到正确位置
sink(1);
return max;
}
/* 上浮第 x 个元素,以维护最大堆性质 */
private void swim(int x) {
// 如果浮到堆顶,就不能再上浮了
while (x > 1 && less(parent(x), x)) {
// 如果第 x 个元素比上层大
// 将 x 换上去
swap(parent(x), x);
x = parent(x);
}
}
/* 下沉第 x 个元素,以维护最大堆性质 */
private void sink(int x) {
// 如果沉到堆底,就沉不下去了
while (left(x) <= size) {
// 先假设左边节点较大
int max = left(x);
// 如果右边节点存在,比一下大小
if (right(x) <= size && less(max, right(x)))
max = right(x);
// 结点 x 比俩孩子都大,就不必下沉了
if (less(max, x)) break;
// 否则,不符合最大堆的结构,下沉 x 结点
swap(x, max);
x = max;
}
}
/* 交换数组的两个元素 */
private void swap(int i, int j) {
Key temp = pq[i];
pq[i] = pq[j];
pq[j] = temp;
}
/* pq[i] 是否比 pq[j] 小? */
private boolean less(int i, int j) {
return pq[i].compareTo(pq[j]) < 0;
}
/* 还有 left, right, parent 三个方法 */
}
栈实现队列、队列实现栈
232. 用栈实现队列 - 力扣(Leetcode)
双栈
232. 用栈实现队列 - 力扣(Leetcode)
将队列头部n-1个元素全部出队再入队,队尾元素(栈顶)就能出队了