算法高频题目

LRUCache实现

思路:使用linkedHashMap。按照插入顺序的有序链表。 get 操作。cache不包含,返回-1。包含。我们需要当前key重新put。 /将 key 变为最近使用
put。如果包含。修改当前key值。然后将key变成最近使用。不包含。如果cacheSize大于当前最大size。我们需要溢出最近没有使用的。那就是链表的最后一个元素。链表的头部。

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);
    }
}


public class LRUCache {
    //双链表  从左往右使用减少
    class DLinkedNode{
        int key, val;
        DLinkedNode pre;
        DLinkedNode next;
        public DLinkedNode(){}
        public DLinkedNode(int _key, int _val) {
            this.key = _key;
            this.val = _val;
        }
    }

    DLinkedNode tail, head;  //双链表头指针和尾部指针
    HashMap cache = new HashMap<>();
    int size;    //当前元素数量
    int capacity;  //容量

    //1.初始化
    public LRUCache(int _capacity) {
        this.capacity = _capacity;
        this.size = 0;
        tail = new DLinkedNode();
        head = new DLinkedNode();
        head.next = tail;
        tail.pre = head;
    }
    
    public int get(int key) {
        DLinkedNode node = cache.get(key);

        if(node == null){
            //不存在key
            return -1;
        }else {
            //使用了该数,更新缓存
            deleteNode(node);
            addToHead(node);
        }
        return node.val;
    }
    
    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);

        //如果存在,修改并更新缓存;
        if(node != null){
            node.val = value;
            deleteNode(node);
            addToHead(node);
        }else {
            //不存在
            //1.判断容量  达到最大容量,删除最近未使用节点(别忘了cache也要删)
            if(size == capacity){
                DLinkedNode removeNode = tail.pre;
                deleteNode(removeNode);
                cache.remove(removeNode.key);
                size--;
            }
            DLinkedNode newNode = new DLinkedNode(key, value);
            size++;
            addToHead(newNode);
            cache.put(key, newNode);
        }
    }

    //删除双链表中的节点
    public void deleteNode(DLinkedNode node){
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    //加入到链表头部
    public void addToHead(DLinkedNode node){
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
    }  
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

你可能感兴趣的:(面试算法,算法)