leetCode LRU Cache

本文探讨了如何解决LeetCode上的LRU Cache问题。内容涉及设计一个数据结构,该结构支持高效的get和set操作。当缓存满时,会根据最近最少使用原则(LRU)移除旧的键值对。作者最初尝试用双向链表实现,但发现其时间复杂度高达O(n^2),导致超时。文章中包含了作者的初步代码实现。

https://oj.leetcode.com/problems/lru-cache/


这个题目的大体意思是,为LRU设计一种数据结构,使得能够支持get和set操作。

get(key)表示,如果cache里面存在key的value的话,就返回value,否则返回-1;

set(key,value)表示,如果cache里面存在key 的话,就更改key对应的value值,否则就加入新的(key,value)对,

如果(key,value)对的个数超过cache的容量的话,就删除最不经常使用的(key,value)对,加入新的(key,value)对。



首先我使用的是双向链表做的。时间复杂度是O(n^2)。是超时的。

代码如下:


public class LRUCache {
    
    
	class Node
	{
		int key;
		int value;
		Node next;
		Node preNode;
		public Node() {
			// TODO Auto-generated constructor stub
			next = null;
		}
		public Node(int k,int v)
		{
			key = k;
			value = v;
			next = null;
			preNode =null;
		}
	}
	
	int Capacity;
	int currentCount=0;
	Node head;
	Node tail;  
    
    public LRUCache(int capacity) {
		Capacity = capacity;
		currentCount = 0;
		head = new Node();
		tail = head;
    }
    
    public int get(int key) {
        
		if(currentCount==1)
		{
			if(head.next.key==key)
				return head.next.value;
		}
		
		if(Capacity>1){
			
			Node tempNode = head.next;
			while(tempNode!=null)
			{
				if(tempNode.key == key)
				{
				    if(tempNode==head.next)
						return tempNode.value;
				    if(tempNode==tail)
					{
						tail = tail.preNode;
						
					}
					tempNode.preNode.next = tempNode.next;
					if(tempNode.next!=null)
					{
						tempNode.next.preNode = tempNode.preNode;
					}
					
					tempNode.next = head.next;
					tempNode.next.preNode = tempNode;
					
					tempNode.preNode = head;
					head.next =tempNode;
					
					return tempNode.value;
				}
				tempNode = tempNode.next;
			}
		}
		
		return -1;
    }
    
    public void set(int key, int value) {
            int getkey=get(key);
            if(getkey!=-1)
    		{
    			head.next.value = value;
    			return;
    		}
       		if(Capacity>currentCount){
			
			if(currentCount == 0){
				
				head.next = new Node(key,value);
				head.next.preNode = head;
				tail = tail.next;
			}
			else {
				
				Node tempNode = new Node(key,value);
				
				tempNode.next = head.next;
				tempNode.next.preNode = tempNode;
				
				tempNode.preNode = head;
				head.next = tempNode;
				
			}
			
			currentCount++;
		
		}
		else {
			
			Node tempNode = new Node(key,value);
			
			tempNode.next = head.next;
			tempNode.next.preNode = tempNode;
			
			tempNode.preNode = head;
			head.next = tempNode;
			
			tail = tail.preNode;
			tail.next = null;
		}
    }
}

为了优化算法,我使用了双向链表+散列表的方法。时间复杂的是O(n)。

public class LRUCache {
    
    	class Node{
		int key;
		int value;
		Node next;
		Node preNode;
		public Node(int k,int v){
			key = k;
			value = v;
			next = null;
			preNode = null;
		}
	}
	
	int Capacity;
	int currentCount=0;
	Node head;
    Node tail;
    HashMap<Integer, Node>map;
    
    public LRUCache(int capacity) {
		Capacity = capacity;
		currentCount = 0;
		head = new Node(-1,-1);
		tail = head;
		map = new HashMap<Integer,Node>();
		map.clear();
    }
    
    public void putHead(Node tempNode){
    	
    	if(tempNode==head.next)return;
    	if(tempNode == tail){
    		tail = tail.preNode;
    		tempNode.preNode = null;
    		tail.next = null;
    	}
    	else{
    		tempNode.preNode.next = tempNode.next;
    		tempNode.next.preNode = tempNode.preNode;
    	}
    	
    	tempNode.next = head.next;
    	head.next.preNode = tempNode;
    	
    	tempNode.preNode = head;
    	head.next = tempNode;
		
    }
    
    public int get(int key) {
    	
    	if(map.containsKey(key)){
    		Node getNode = map.get(key);
    		putHead(getNode);
			return getNode.value;
		}
    	else {
			return -1;
		}
		
    }
    
    public void set(int key, int value) {
           
    	Node getNode = map.get(key);
    	if(getNode==null){
    		
    		Node tempNode = new Node(key, value);
    		map.put(key, tempNode);
    		
    		if(currentCount<Capacity){
    			
    			if(currentCount == 0){
    				head.next = tempNode;
    				tempNode.preNode = head;
    				tail = tempNode;
    			}
    			else {
					tempNode.next = head.next;
					head.next.preNode = tempNode;
					
					head.next = tempNode;
					tempNode.preNode = head;
				}
    			currentCount++;
    		}
    		else {
				map.remove(tail.key);
				tail = tail.preNode;
				tail.next.preNode = null;
				tail.next = null;
				
				tempNode.next = head.next;
				if(head.next!=null){
					head.next.preNode = tempNode;
				}
				tempNode.preNode = head;
				head.next = tempNode;
			}
    		
    	}
    	else {
    		putHead(getNode);
    		getNode.value = value;
		}
	
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值