Leetcode 146) LRU Cache
in Algorithms

내 풀이
- LinkedHashMap 사용했다.. 성능 쓰레기임. Hashmap은 순서가 딱히 없고, LinkedHashMap은 들어온 순서가 있다.
- 아무래도 이 문제의 의도는 LinkedHashMap을 쓰는건 아니었던듯 싶다…
- 다시 풀기. 이번엔 Doubly Linkedlist로
class LRUCache {
    int cnt=0;
    Map<Integer,Integer> source = new LinkedHashMap<>();
    public LRUCache(int capacity) {
        cnt=capacity;
    }
    public int get(int key) {
        int i=0;
        if(source.get(key)!=null){
            int val=source.get(key); 
            source.remove(key);
            source.put(key,val);
            return val;}
        return -1;
    }
    public void put(int key, int value) {
        if(source.get(key)!=null){
            source.remove(key);
            source.put(key,value);
            return;
        }       
        if(cnt==0){
            int a = source.keySet().stream().findFirst().get();
            System.out.println(a);
            System.out.println(key);
            source.remove(a);
            cnt++;
        }
        source.put(key,value);
        cnt--;
    }
}
/**
 * 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);
 */
- double linked list로 다시 풀어봄 - class LRUCache { class Node { int key; int val; Node(int key,int val){ this.key = key; this.val = val; } Node(){} Node next = null; Node prev = null; } int capacity; Map<Integer, Node> cache; Node head;Node tail; public LRUCache(int capacity) { this.capacity=capacity; //key와 노드 cache = new HashMap<>(); head = new Node(); tail = new Node(); head.next= tail; tail.prev=head; } public int get(int key){ if(cache.containsKey(key)){ moveBack(cache.get(key)); return cache.get(key).val; }else{ return -1; } } public void put(int key, int value) { if(cache.containsKey(key)){ cache.get(key).val =value; moveBack(cache.get(key)); }else{ if(capacity<=cache.size()){ // System.out.println("remove what? " + head.next.key); cache.remove(head.next.key); head.next=head.next.next; head.next.prev=head; } Node a = new Node(key, value); tail.prev.next= a; a.prev=tail.prev; tail.prev=a; a.next=tail; cache.put(key, a); } } public void moveBack(Node cur){ // System.out.println("move what? " + cur.key); cur.prev.next =cur.next; cur.next.prev=cur.prev; tail.prev.next=cur; cur.prev=tail.prev; tail.prev=cur; cur.next=tail; // System.out.println("head? " + head.next.key); // System.out.println("tail? " + tail.prev.key); } } /** * 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); */
다른 답안
class LRUCache {
    class Node{
        int value;
        int key;
        Node next = null;
        Node prev = null;
        Node(int v, int k){
            value = v;
            key = k;
        }
    }
    
    Node head = null, tail = null;
    HashMap<Integer, Node> map = new HashMap<>();
    int capacity = 0;
    int size = 0;
    public LRUCache(int capacity) {
        this.capacity = capacity;
    }
    
    public int get(int key) {
        if(!map.containsKey(key))
            return -1;
        Node n = map.get(key);
        moveNodeToFront(n);
        return n.value;
    }
    
    private void moveNodeToFront(Node n){
        if(n == head)
            return;
        if(n == tail){
            n.prev.next = null;
            tail = n.prev;
            n.next = head;
            head.prev = n;
            n.prev = null;
            head = n;
        }else{
            n.prev.next = n.next;
            n.next.prev = n.prev;
            n.next = head;
            head.prev = n;
            n.prev = null;
            head = n;
        }
    }
    public void put(int key, int value) {
        if(map.containsKey(key)){
            Node n = map.get(key);
            n.value = value;
            moveNodeToFront(n);
            return;
        }
        if(size == capacity){
            size--;
            map.remove(tail.key);
            if(tail == head){
                tail = head = null;
            }else{
                tail = tail.prev;
                tail.next = null;
            }
        }
        
        Node n = new Node(value, key);
        map.put(key, n);
        size++;
        if(head == null){
            head = tail = n;
        }else{
            n.next = head;
            head.prev = n;
            head = n;
        }        
    }
}
/**
 * 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);
 */
오답노트
- head랑 tail을 dummy로 해서 위치를 지켜주면 exception 신경쓸게준다…!! - 원소가 하나일때, 다 사라졌을 때 등등 이럴때 if문으로 head tail 다시 설정 안해줘도 되니까 생각해야하는 경우의 수가 줄어든다.
 - //이렇게 head인 노드를 직접 가리키기보다는 Node head; Node tail; //head,tail을 할당하고 head.next에 진짜 head를 넣는다. Node head= new Node(); Node tail = new Node();
- ………. 흠.. 푸느라 ㅈㄴ 오래걸렸다. 링크 하나를 안했는데 모르고 있었음. 양방향인지 확인 안한 내 잘못… 
class LRUCache {
    class Node{
        int key;int value;
        Node next=null;
        Node prev =null;
        Node(){
        }
        Node(int k, int v){
            key=k;value=v;
        }
    }
    int max; 
    Node head = new Node(); 
    Node tail = new Node();
    Map<Integer,Node> m = new HashMap<>();
    public LRUCache(int capacity) {
        max=capacity;
        head.next= tail;
        tail.prev= head;
    }
    public int get(int key){
        if(m.containsKey(key)){
            changePosition(m.get(key));
            return m.get(key).value;
        }
        return -1;
    }
    public void changePosition(Node cur){
        Node a = cur.prev;
        Node b= cur.next;
        a.next=b;
        b.prev = a;
        cur.prev= tail.prev;
        tail.prev.next=cur;
        cur.next=tail;
        tail.prev=cur;
    }
    public void put(int key, int value) {
        if(!m.containsKey(key)){
            if(max==m.size()){
                Node old = head.next;
                head.next=old.next;
                old.next.prev=head;
                m.remove(old.key);
            }
            Node newNode= new Node(key,value);
            m.put(key,newNode);
            tail.prev.next=newNode;
            newNode.prev=tail.prev;
            newNode.next=tail;
            tail.prev=newNode;        
        }else{
            //key 이미 있는 경우
            changePosition(m.get(key));
            m.get(key).value= value;
        }
    }
}
/**
 * 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);
 */
