LeetCode 第146题:LRU缓存机制

2020-07-26  本文已影响0人  放开那个BUG

1、前言

题目描述

2、思路

所谓的 LRU,指的是,get 某一个 key,如果 key 存在,那么这个 <key,value> 要放到最新的位置。

如果 set 一个 <key,value>,如果这个 key 已经存在,那么要改变原先 value 的值,并把它放到最新的位置;如果这个 key 不存在,那么先要观察容量满没有,满了则先删除最近不使用的节点,然后将 <key,value> 放到最新位置;否则直接把 <key,value> 放到最新位置。

3、代码

import java.util.HashMap;
import java.util.Map;

class LRUCache {

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

    private ListNode head, last;

    private Integer capacity;

    public LRUCache(int capacity) {
        this.head = new ListNode(null, null,  -1, -1);
        this.last = new ListNode(null, null, -1, -1);
        head.next = last;
        last.pre = head;
        this.capacity = capacity;
    }
    
    public int get(int key) {
        ListNode node = map.get(key);
        if(node == null){
            return -1;
        }

        moveToHead(node);
        return node.value;
    }
    
    public void put(int key, int value) {
        // 有重复的重新赋值并移动到前面即可
        // 如果直接判断大小,很可能出现这种情况:容量为2,{1=1, 2=2},后面再 put(1,3),直接判断会导致 2=2 没了,直接变成了 {1=3}
        ListNode node = map.get(key);
        if(node != null){
            node.value = value;
            moveToHead(node);
            return;
        }

        if(map.size() + 1 > capacity){
            ListNode lastNode = removeLast();
            map.remove(lastNode.key);
        }
        node = new ListNode(null, null, key, value);
        map.put(key, node);
        linkHead(node);
    }

    /**
     * 将节点链接到最后
     * @param node
     */
    private void linkHead(ListNode node) {
        ListNode nextNode = head.next;
        node.pre = head;
        node.next = nextNode;
        nextNode.pre = node;
        head.next = node;
    }

    /**
     * 将最后一个节点去掉
     * @return
     */
    private ListNode removeLast() {
        ListNode lastNode = last.pre;
        //删除节点
        removeNode(lastNode);
        return lastNode;
    }

    /**
     * 将要访问的节点移动最前面
     * @param node
     */
    private void moveToHead(ListNode node) {
        // 先删除节点
        removeNode(node);
        linkHead(node);
    }

    /**
     * 删除节点
     * @param node
     */
    private void removeNode(ListNode node) {
        ListNode preNode = node.pre;
        ListNode nextNode = node.next;
        preNode.next = nextNode;
        nextNode.pre = preNode;
        node.pre = null;
        node.next = null;
    }

    class ListNode {
        ListNode next;
        ListNode pre;
        Integer key;
        Integer value;

        public ListNode(ListNode next, ListNode pre, Integer key, Integer value) {
            this.next = next;
            this.pre = pre;
            this.key = key;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        LRUCache lRUCache = new LRUCache(2);
        lRUCache.put(1, 1); // 缓存是 {1=1}
        lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
        System.out.println(lRUCache.get(1));    // 返回 1
        lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
        System.out.println(lRUCache.get(2));    // 返回 -1 (未找到)
        lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
        System.out.println(lRUCache.get(1));    // 返回 -1 (未找到)
        System.out.println(lRUCache.get(3));    // 返回 3
        System.out.println(lRUCache.get(4));    // 返回 4
    }
}
上一篇 下一篇

猜你喜欢

热点阅读