leetcode 146. LRU Cache

=======================2019.1.18====================

双向链表+hashmap。双向链表存key的先后顺序消息,hashmap快速定位元素。

class LRUCache {
    Node first;
    Node end;
    final int K;
    int cap;
    HashMap<Integer,Node> map;
    public LRUCache(int capacity) {
        map=new HashMap<>();
        first=new Node(0,0);
        end=new Node(0,0);
        K=capacity;
        first.next=end;
        end.pre=first;
    }
    
    public int get(int key) {
        if(map.get(key)==null) return -1;
        Node node=map.get(key);
        node.pre.next=node.next;
        node.next.pre=node.pre;
        
        node.next=end;
        node.pre=end.pre;
        end.pre.next=node;
        end.pre=node;
        
        return node.val;
    }
    
    public void put(int key, int value) {
        if(map.get(key)!=null){
            map.get(key).val=value;
            get(key);
        }else{
            Node node=new Node(key,value);
            map.put(key,node);
            
            node.pre=end.pre;
            node.next=end;
            end.pre.next=node;
            end.pre=node;

            if(cap==K){
                Node n=first.next;
                map.remove(n.key);
                first.next=n.next;
                n.next.pre=first;
            }else{
                cap++;
            }
        }
    }
    class Node{
        int key;
        int val;
        Node pre;
        Node next;
        Node(int key,int val){
            this.key=key;
            this.val=val;
        }
    }
}

===================================================

双向链表实现LRU Cache

注意1.各种边界条件(改节点位置的时候考虑节点目前的位置)

       2.查找到,插入(分update,set)都要考虑找到元素的位置的修改。

复杂度get,set为O(n)

public class LRUCache {
    int capacity;
    int count=0;
    Node begin;//起始结束标记节点,可以简化处理边界条件
    Node end;
    class Node{
        Node pre;  
        Node next;
        int key;
        int value;
        Node(Node pre,Node next,int key,int value){
            this.pre=pre;
            this.next=next;
            this.key=key;
            this.value=value;
        }
    }
    /*
    * @param capacity: An integer
    */public LRUCache(int capacity) {
        this.capacity=capacity;
        begin=new Node(null,null,0,0);
        end=new Node(begin,null,0,0);
        begin.next=end;
    }

    /*
     * @param key: An integer
     * @return: An integer
     */
    public int get(int key) {
        Node pretemp;
        Node nexttemp;
        for(Node node=begin.next;node!=end;node=node.next){
            pretemp=node.pre;
            nexttemp=node.next;
            //注意边界条件,它不是begin下一个节点,不然会修改自己!!!!!!
            if(node.key==key){
                if(node.pre!=begin){
                    //把此节点放到头部,需要记录他的前一个节点,和后一个节点,并连接
                    //放到头节点,前面的节点是最近使用过的
                    begin.next.pre=node;
                    node.next=begin.next;
                    node.pre=begin;
                    begin.next=node;
                    //连接他的上一个节点和下一个节点
                    pretemp.next=nexttemp;
                    nexttemp.pre=pretemp;
                }
                return node.value;
            }
        }
        return -1;
    }

    /*
     * @param key: An integer
     * @param value: An integer
     * @return: nothing
     */
    public void set(int key, int value) {
        //找到的话数据也要移动到最前面
        Node pretemp;
        Node nexttemp;
        for(Node node=begin.next;node!=end;node=node.next){
            //坑!!找到key值也要把节点放在前面!!!!!
            pretemp=node.pre;
            nexttemp=node.next;
            if(node.key==key){
                if(node.pre!=begin){
                //把此节点放到头部,需要记录他的前一个节点,和后一个节点,并连接
                //放到头节点,前面的节点是最近使用过的
                    begin.next.pre=node;
                    node.next=begin.next;
                    node.pre=begin;
                    begin.next=node;
                    //连接他的上一个节点和下一个节点
                    pretemp.next=nexttemp;
                    nexttemp.pre=pretemp;
                }
                node.value=value;
                return;
            }
        }
        //没找到的话,插入到最前面
        Node node=new Node(begin,begin.next,key,value);
        begin.next.pre=node;
        begin.next=node;
        count++;
        if(count>capacity){
            //把最后一项删除
            end.pre.pre.next=end;
            end.pre=end.pre.pre;
            count--;
        }
    }
}

改进参考:

http://www.bubuko.com/infodetail-430031.html

 

那就是利用链表和hashmap (Map<Integer, Node>)(时间复杂度O(1),hashMap经常能把复杂度改进到O(1))

 

  1)set(key,value):如果key在hashmap中存在,则先重置对应的value值,然后获取对应的节点cur,将cur节点从链表删除,并移动到链表的头部;若果key在hashmap不存在,则新建一个节点,并将节点放到链表的头部。当Cache存满的时候,将链表最后一个节点删除即可。

  2)get(key):如果key在hashmap中存在,则把对应的节点放到链表头部,并返回对应的value值;如果不存在,则返回-1。

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值