• LeetCode OJ


    这题AC的前提是get()和set()操作都得是O(1),不过题中没有说明这点(所以我一开始Naive的用了两个数组分别表示Key 和Value,想都不用想每个操作定然会达到N)。后来是看了discuss后,决定采用HashMap+LinkedList,但是结果还是一直TLE,其实TLE是预料中的,因为LinkedList的底层虽然是双向链表,我们在remove其中一个元素时,需要先通过遍历链表才能找到这个元素,这个遍历就使得时间复杂度为O(n)。

    最后在网上看到这样一个blog ,我觉得里头一个数据结构画的特别形象,如下:

    有了这个提示,写自己的代码并不难,但是双向链表的操作特别需要细心和耐心,很容易出错。下面是我的Java代码,已AC。

      1 package leetcode;
      2 
      3 import java.util.HashMap;
      4 /**
      5  * 自己建一个双向链表
      6  * 表头表示最新使用过得、表尾表示latest least used
      7  * 采用LinkedList<E>没法在O(1)的时间内删除某个节点(我感觉是这样)
      8  * @author Echo
      9  *
     10  */
     11 class DNode
     12 {
     13     int key;
     14     int value;
     15     DNode next;
     16     DNode pre;
     17     public DNode()
     18     {
     19     }
     20     public DNode(int k, int v)
     21     {
     22         key = k;
     23         value = v;
     24     }
     25 }
     26 /**
     27  * 下面是LRU这个类
     28  * @author Echo
     29  *
     30  */
     31 public class LRUCache1 {
     32     //key和DNode是很明显的对应关系,并且hash表中的value之间又是双向链表
     33     HashMap<Integer,DNode> KV ; //这个数据结构可以参考 http://www.programcreek.com/2013/03/leetcode-lru-cache-java/
     34     DNode head ; //表示双向链表的表头
     35     DNode tail ; //表示双向链表的表尾
     36     int cap; //cache的容量
     37     int sz = 0; //cache的实际size
     38     public LRUCache1(int capacity)
     39     {
     40         cap = capacity;
     41         KV = new HashMap<Integer,DNode>(cap); 
     42     }
     43     /**
     44      *  Get the value (will always be positive) of the key if the key exists in the cache,
     45      *  otherwise return -1.
     46      * @param key
     47      * @return
     48      */
     49     public int get(int key)
     50     {
     51         if(KV.containsKey(key))
     52         {
     53             DNode u = KV.get(key);    
     54             remove(u);
     55             addHead(u);
     56             KV.put(key, u);
     57             return u.value;
     58         }
     59         return -1;
     60     }
     61     /**
     62      * Set or insert the value if the key is not already present. 
     63      * When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
     64      * @param key
     65      * @param value
     66      */
     67     public void set(int key, int value)
     68     {
     69         DNode u = new DNode(key,value);
     70         if(get(key) == -1)
     71         {    
     72             if(sz<cap)
     73             {
     74                 KV.put(key, u);
     75                 addHead(u);
     76                 sz++;
     77             }
     78             else{
     79                 int tailK = tail.key;
     80                 KV.remove(tailK);
     81                 if(tail == head)
     82                 {
     83                     tail = null;
     84                     head = null;
     85                     addHead(u);
     86                     KV.put(key, u);
     87                 }else{
     88                     DNode temp = tail.pre;
     89                     temp.next = null;
     90                     tail = temp;
     91                     addHead(u);
     92                     KV.put(key, u);
     93                 }
     94                 
     95             }
     96         }else
     97         
     98             KV.get(key).value = value;    
     99     }
    100     private void addHead(DNode u) {
    101         // TODO Auto-generated method stub
    102         if(head == null)
    103         {
    104             head = u;
    105             tail = u;
    106         }else{
    107             head.pre = u;
    108             u.next = head;
    109             head = u;
    110             u.pre = null;
    111         }
    112         
    113         //return head;
    114     }
    115     private DNode remove(DNode n)
    116     {
    117         DNode pre = n.pre;
    118         DNode next = n.next;
    119         if(pre == null && next == null)
    120         {
    121             head = null;
    122             tail = null;
    123             return null;
    124         }
    125         if(pre == null)
    126         {
    127             n.next.pre = null;
    128             head = n.next;
    129             return n.next;
    130         }
    131         if(next == null)
    132         {
    133             n.pre.next = null;
    134             tail = n.pre;
    135             return n.pre;
    136         }
    137         pre.next = n.next;
    138         next.pre = pre;
    139         return pre;
    140     }
    141     /**
    142      * @param args
    143      */
    144     public static void main(String[] args) {
    145         // TODO Auto-generated method stub
    146         LRUCache1 lu = new LRUCache1(1);
    147         lu.set(2, 1);
    148         System.out.println(lu.get(2));
    149         lu.set(3,2);
    150         System.out.println(lu.get(2));
    151         System.out.println(lu.get(3));
    152     }
    153 
    154 }
    有问题可以和我联系,bettyting2010#163 dot com
  • 相关阅读:
    「SAM」你的名字
    「疫期颓废」2
    「疫期颓废」1
    代码覆盖率简单介绍
    解决git报ssh variant 'simple' does not support setting port
    接口自动化基本流程和测试思路
    wait和sleep的区别
    vm垃圾回收算法的简单理解
    TCP-三次握手和四次挥手简单理解
    浏览器输入一个url 中间经历的过程
  • 原文地址:https://www.cnblogs.com/echoht/p/3681908.html
Copyright © 2020-2023  润新知