LeetCode-中-146。LRUキャッシュ

トピック

  • 設計
  • ハッシュ表
  • リンクリスト

説明

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

最近使用されていない(LRU)キャッシュの制約に従うデータ構造を設計します

LRUCacheクラスを実装します。

  • LRUCache(int capacity)LRUキャッシュを正のサイズで初期化しますcapacity
  • int get(int key)keyキーが存在する場合はの値を返し、存在しない場合はを返し-1ます。
  • void put(int key, int value)keyキーが存在する場合は、の値を更新しますそれ以外の場合は、key-valueペアをキャッシュに追加します。キーの数がcapacityこの操作のを超える場合は、最も使用頻度の低いキーを削除します。

フォローアップ
あなたができるgetputしてO(1)時間複雑?

例1

Input
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]

Explanation
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // cache is {1=1}
lRUCache.put(2, 2); // cache is {1=1, 2=2}
lRUCache.get(1);    // return 1
lRUCache.put(3, 3); // LRU key was 2, evicts key 2, cache is {1=1, 3=3}
lRUCache.get(2);    // returns -1 (not found)
lRUCache.put(4, 4); // LRU key was 1, evicts key 1, cache is {4=4, 3=3}
lRUCache.get(1);    // return -1 (not found)
lRUCache.get(3);    // return 3
lRUCache.get(4);    // return 4

制約

  • 1 <= capacity<= 3000
  • 0 <= key<= 3000
  • 0 <= value<= 1 0 4 10 ^ 41 04
  • 最大で3 * 1 0 4 10 ^ 41 04つの呼び出しはについて説明するgetput

分析

方法1:LinkedHashMapを使用する

方法2:ハッシュテーブル+二重リンクリスト

提出

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

//方法一
public class LRUCache {
    
    
	
	private LinkedHashMap<Integer, Integer> cache;
	
    public LRUCache(int capacity) {
    
    
        cache = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true){
    
    
        	
			private static final long serialVersionUID = 1L;
			

			@Override
        	protected boolean removeEldestEntry(java.util.Map.Entry<Integer, Integer> eldest) {
    
    
        		return size() > capacity;
        	}
        	
        };
    }
    
    public int get(int key) {
    
    
    	return cache.getOrDefault(key, -1);
    }
    
    public void put(int key, int value) {
    
    
        cache.put(key, value);
    }
    
    @Override
    public String toString() {
    
    
    	return cache.toString();
    }
    
}

//方法二
class LRUCache2{
    
    
	class Node<K, V>{
    
    
		K key;
		V value;
		Node<K, V> prev;
		Node<K, V> next;
		
		public Node() {
    
    
			this.prev = this.next = null;
		}
		public Node(K key, V value) {
    
    
			super();
			this.key = key;
			this.value = value;
		}
	}
	
	class DoublyLinkedList<K, V>{
    
    
		Node<K, V> head;
		Node<K, V> tail;
		
		public DoublyLinkedList() {
    
    
			this.head = new Node<K, V>();
			this.tail = new Node<K, V>();
			this.head.next = this.tail;
			this.tail.prev = this.head;
		}
		
		public void addHead(Node<K, V> node) {
    
    
			node.next = this.head.next;
			node.prev = this.head;
			this.head.next.prev = node;
			this.head.next = node;
		}
		
		public void removeNode(Node<K, V> node) {
    
    
			node.prev.next = node.next;
			node.next.prev = node.prev;
			node.prev = null;
			node.next = null;

		}
		
		public Node<K, V> getLast() {
    
    
			if(this.tail.prev == this.head)
				return null;
			return this.tail.prev;
		}

	}
	
	private int cacheSize;
	private Map<Integer, Node<Integer, Integer>> map;
	private DoublyLinkedList<Integer, Integer> doublyLinkedList;
	
	
	public LRUCache2(int cacheSize) {
    
    
		this.cacheSize = cacheSize;
		map = new HashMap<>();
		doublyLinkedList = new DoublyLinkedList<>();
	}

	public int get(int key) {
    
    
		if(!map.containsKey(key)) {
    
    
			return -1;
		}
		
		Node<Integer, Integer> node = map.get(key);
		doublyLinkedList.removeNode(node);
		doublyLinkedList.addHead(node);
		
		return node.value;
	}
	
	public void put(int key, int value) {
    
    
		
		if(map.containsKey(key)) {
    
    
			
			Node<Integer, Integer> node = map.get(key);
			node.value = value;
			map.put(key, node);
			
			doublyLinkedList.removeNode(node);
			doublyLinkedList.addHead(node);
		}else {
    
    
			
			if(map.size() == cacheSize) {
    
    
				Node<Integer, Integer> lastNode = doublyLinkedList.getLast();
				map.remove(lastNode.key);
				doublyLinkedList.removeNode(lastNode);
			}
			
			Node<Integer, Integer> newNode = new Node<>(key, value);
			map.put(key, newNode);
			doublyLinkedList.addHead(newNode);
		}
	}
}

テスト

import static org.junit.Assert.*;


import org.junit.Test;

public class LRUCacheTest {
    
    

	@Test
	public void test() {
    
    
		LRUCache obj = new LRUCache(2);

		obj.put(1, 1);
		obj.put(2, 2);
		assertEquals(1, obj.get(1));
		obj.put(3, 3);
		assertEquals(-1, obj.get(2));
		//System.out.println(obj);
		
		obj.put(4, 4);
		assertEquals(-1, obj.get(1));
		assertEquals(3, obj.get(3));
		assertEquals(4, obj.get(4));
	}
	
	@Test
	public void test2() {
    
    
		LRUCache2 obj = new LRUCache2(2);
		
		obj.put(1, 1);
		obj.put(2, 2);
		assertEquals(1, obj.get(1));
		obj.put(3, 3);
		assertEquals(-1, obj.get(2));
		//System.out.println(obj);
		
		obj.put(4, 4);
		assertEquals(-1, obj.get(1));
		assertEquals(3, obj.get(3));
		assertEquals(4, obj.get(4));
	}
}

おすすめ

転載: blog.csdn.net/u011863024/article/details/115263747