【Leetcode刷题篇】leetcode146 LRU缓存机制

运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。

实现 LRUCache 类:
LRUCache(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存
int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
void put(int key, int value) 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。

进阶:你是否可以在 O(1) 时间复杂度内完成这两种操作?

示例:
输入
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4

解题思路一、直接继承LinkedHashMap来实现。

	class LRUCache extends LinkedHashMap<Integer,Integer> {
		private int capacity;
		
	    public LRUCache(int capacity) {
	    	super(capacity,0.75F,true);
	    	this.capacity = capacity;
	    }
	    
	    public int get(int key) {
			return super.getOrDefault(key, -1);

	    }
	    
	    public void put(int key, int value) {
	    	super.put(key, value);
	    }
	    
	    @Override
	    	protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
	    		// TODO Auto-generated method stub
	    		return size()>capacity;
	    	}
	}

题解二、双向链表+hashmap来实现。

package com.lcz.leetcode;

import java.util.HashMap;

public class Leetcode146_2 {
	class LRUCache {
		// 双向链表
		class DLinkedNode{
			int key;
			int value;
			DLinkedNode prev;
			DLinkedNode next;
			public DLinkedNode() {
				
			}
			public DLinkedNode(int key,int value) {
				this.key = key;
				this.value = value;
			}
		}
		// hashmap
		private HashMap<Integer,DLinkedNode> cache = new HashMap<>();
		// 定义一些变量
		private int size;
		private int capacity;
		private DLinkedNode head,tail;
		
	    public LRUCache(int capacity) {
	    	this.size = 0;
	    	this.capacity = capacity;
	    	// 生成伪头部和伪尾部结点
	    	head = new DLinkedNode();
	    	tail = new DLinkedNode();
	    	head.next = tail;
	    	tail.prev = head;
	    }
	    
	    public int get(int key) {
			DLinkedNode node = cache.get(key);
			if(node==null) {
				return -1;
			}else {
				// 如果key存在,则哈希表定位,节点移动到头部
				moveToHead(node);
				return node.value;
			}
	    }
	    
	    public void put(int key, int value) {
	    	DLinkedNode node = cache.get(key);
	    	if(node==null) {
	    		// 如果key不存在,则创建一个新的结点
	    		DLinkedNode newNode = new DLinkedNode(key,value);
	    		// 添加到哈希表中
	    		cache.put(key,newNode);
	    		// 添加到双向链表的头部
	    		addToHead(newNode);
	    		++size;
	    		//判断容量是否足够
	    		if(size>capacity) {
	    			//超出容量,则删除双向链表的尾部结点
	    			DLinkedNode tail = removeTail();
	    			// 删除哈希表中对应的项
	    			cache.remove(tail.key);
	    			--size;
	    		}
	    	}else {
	    		// key存在,哈希表定位,修改key,移动头部
	    		node.value = value;
	    		moveToHead(node);
	    	}
	    }
	    
	    // 添加到头部
	    private void addToHead(DLinkedNode node) {
	    	node.prev = head;
	    	node.next = head.next;
	    	head.next.prev = node;
	    	head.next = node;
	    }
	    // 删结点
	    private void removeNode(DLinkedNode node) {
	    	node.prev.next = node.next;
	    	node.next.prev = node.prev;
	    }
	   // 移动头结点 分两步,删结点,填结点
	    private void moveToHead(DLinkedNode node) {
	    	removeNode(node);
	    	addToHead(node);
	    }
	    
	    // 删除尾部结点
	    private DLinkedNode removeTail() {
	    	DLinkedNode res = tail.prev;
	    	removeNode(res);
	    	return res;
	    }
	    
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mind_programmonkey

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

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

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

打赏作者

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

抵扣说明:

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

余额充值