Problem 1 LRU cache

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

have been updated to new version

What is cache

  • 为了不每次都重新检索,所先把检索的结果存下来,下次用户访问的时候直接给存好的检索结果

  • 想到的是Map<key, value>, get a key by O(1)

  • look up operation(memo),如果计算过了,get上次计算的过,否则就重新算一遍

  • Cache 的本质就是map,只不过区别是,他是一个有capacity的map

What is used:

  • 所有的增改查insert, update query都是used

  • put operation == insert/ update

  • get operation == query

  • remove operation == delete

  • 注意,很多时候改,以为着是删/增

数据结构界的打工人:Map

  • Look up something(找什么,就是你所储存的东西) by something(透过什么来找,这个就是key)

  • 经典的Use Case: 我需要知道我自己定义的Entry Reference在哪里,但是我propose的结果不具备优秀的查找功能

    • Map<Key, Entry Reference> locationMap

    • key通过什么找reference,Entry Reference你其他的数据结构储存

  • Example: Array Based PriorityQueue Update(key) Function

    • Map<key, index> indexMapForKeyinHeap + Heap

  • 所有的操作,只要给我一个Key我都是可以拿到Entry Node, 又有了可以对时间排序的TreeSet/TreeMap

Summary

  • hybrid注意data structure, 先考虑每个元素cell里面有什么:

    • cell{key, value, index(hidden)}

  • 再注意,多加结构的时候,必须用cell来做一个单位,会让思路更简单,比如说这道题如果用treeSet

    • map(key, cell) && container(cell)

    • 并不能用map(key, index) && container(cell) , and Cell only have{key, index} ,why???

      • 因为如果你需要知道这个元素里的其他资料

Method 1 TreeSet/ TreeMap + Map

Step 1 Use Case API design

Step 2: Detail Logic

get(key):

  • case 1 : map 里面有这个key

    • 透过Map拿到Entry node(return的data就在里面)

    • update这个Entry Node的时间信息(TreeSet里的这个Entry做update--> delete + insert)

  • case 2: map里面没有这个key

    • return null

  • overall: O(logn)

put(key, value):

  • case 1: map 里面有这个key

    • 想当于update这个key-value pair里的value

    • 通过Map拿到Entry Node

      • update 这个Entry Node的value信息

      • update 这个Entry Node的时间信息

  • case 2: map 里面没有这个key

    • case 2.1 现在没有满

      • 直接放一个新的Entry(update two maps)

    • case 2.2 现在满了

      • 踢出一个leat recently used:也就是TreeSet里面时间戳

  • overall: O(logn)

timeStamp:

  • 设计为当前LRU class里的一个feild

  • updated 准则,任何operation都需要update当前的信息

capacity:

  • 设计为当前LRU class的一个field

  • 注意put的details操作

FYI

TreeSet Version

TreeMap Version

Method 2 DoubleLinkedList

  • 除了treeSet还有什么数据结构可以保持时间顺序? Queue==> FIFO时间顺序

  • Queue逻辑上的数据结构 => 怎么实现Queue

    • Queue<Integer> queue = new ArrayDeque<>();

    • Queue<Integer> queue = new LinkedList<>();

  • 增删改查全是O(1)

    • Queue是逻辑数据结构,底层实现的是LinkedList

    • 而DoubleLinkedList是因为O(1)的删除

  • 那你得给我这个node reference,有了这个node reference,我做什么都是O(1),关键问题是,人家User insert/update/remove/query,人家给你的是key,不是node reference

  • 打工人上线: Map<Key, DoublyListNode> locationMap + DoubleLinkedList(datainfo) DLL

Step 1 Use Case API design

  • get(key)

  • put(key, value)

Step 2: Detail Logic

get(key):

  • case 1 : map 里面有这个key

    • get the key==> 通过map拿到装有data的ListNode ==> ListNode里面的东西就是return的东西

    • update time order ==> remove this ListNode from LinkedList, then insert into Head

  • case 2: map里面没有这个key

    • return null

  • overall: O(logn)

put(key, value):

  • case 1: map 里面有这个key

    • update the value ==> 通过map拿到装有data的ListNode ==》 update ListNode

    • update the order ==> remove this ListNode from LinkedList, then insert into head

  • case 2: map 里面没有这个key

    • case 2.1 the cache is not full (check map 的size到不到capacity)

      • put the key value there

      • update the time order ==> insert into Head

    • case 2.2 现在满了

      • delete the oldest one ==> 踢出tail node

      • put the kye value there ==> insert into map and LL

      • update the time order ==> head

  • overall: O(1)

timeStamp:

  • 设计为当前LRU class里的一个feild

  • updated 准则,任何operation都需要update当前的信息

capacity

  • 设计为当前LRU class的一个field

Last updated