【leetcode常见面试题】146. LRU 缓存

【主要考察点】:哈希表、链表
在这里插入图片描述

解题方法

1. 哈希表+双向链表

  1. 哈希表用来映射元素在双向链表中的位置,另外提供get、put功能。
  2. 双向链表通过不断的调整元素在链表中的位置来实现LRU功能,越最近访问的越靠近链表头部,如果需要淘汰,则直接移除链表尾部元素即可。
import java.util.HashMap;
import java.util.Map;

public class LRUCache {

    // 记录当前集合大小
    int size = 0;
    // 阈值
    int capacity;
    // 虚拟一个头节点(方便边界处理)
    LinkNode head;
    // 虚拟一个尾节点(方便边界处理)
    LinkNode tail;

    Map<Integer, LinkNode> map = new HashMap<>();

    public LRUCache(int capacity) {
        this.capacity = capacity;
        // 初始化头尾节点
        this.head = new LinkNode();
        this.tail = new LinkNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        LinkNode node = map.get(key);
        if (node == null) {
            return -1;
        }
        // 访问过之后,要移动到链表头部
        moveToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        LinkNode node = map.get(key);
        if (node == null) {
            // 构建一个新节点
            LinkNode newNode = new LinkNode(key, value);
            // 添加到链表头节点
            addToHead(newNode);
            size++;
            map.put(key, newNode);
            // 如果此时超过阈值,则移除尾节点
            if (size > capacity) {
                LinkNode tail = removeTail();
                size--;
                map.remove(tail.key);
            }
        } else {
            // 更新value
            node.value = value;
            // 移动到链表头部
            moveToHead(node);
        }
    }

    private LinkNode removeTail() {
        LinkNode node = tail.prev;
        removeNode(node);
        return node;
    }

    private void moveToHead(LinkNode node) {
        // 先把节点从链表中删除
        removeNode(node);
        // 然后再添加到链表头部
        addToHead(node);
    }

    private void removeNode(LinkNode node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void addToHead(LinkNode node) {
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
        node.prev = head;
    }

}

/**
 * 双向链表
 */
class LinkNode {
    int key;
    int value;
    // 前一个节点
    LinkNode prev;
    // 后一个节点
    LinkNode next;

    public LinkNode() {
    }

    public LinkNode(int key, int value) {
        this.key = key;
        this.value = value;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值