设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。 addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。 addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。 addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。 deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点
MyLinkedList linkedList = new MyLinkedList(); linkedList.addAtHead(1); linkedList.addAtTail(3); linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3 linkedList.get(1); //返回2 linkedList.deleteAtIndex(1); //现在链表是1-> 3 linkedList.get(1); //返回3
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。 写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // 返回 1 cache.put(3, 3); // 该操作会使得关键字 2 作废 cache.get(2); // 返回 -1 (未找到) cache.put(4, 4); // 该操作会使得关键字 1 作废 cache.get(1); // 返回 -1 (未找到) cache.get(3); // 返回 3 cache.get(4); // 返回 4
思路:
采用链表+哈希表实现,利用哈希查找的时间复杂度为O(1),链表插入删除元素的时间复杂度为O(1),这里使用双向链表,如果使用单链表的话,删除元素需要保存其前向节点,所以直接使用双向链表;
ltcached的每一个节点是(key,val)对,mp的关键字是key,值为key对应的链表节点的迭代器;
根据LRU规则,判断是否存在key,存在则返回对应的val(由于mp[key]存放的时链表节点的迭代器,所以val = mp[key]->second),删除该元素,并将元素重新插入链表头,若超出容量指责删除链表尾部元素;不存在则返回-1;
插入元素时,若存在,更新值即可,并删除该元素,插入链表头部;若不存在,在容量达到最大值的情况下,删除链表尾部元素;每次更新时,同样需要更新mp中的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 class LRUCache {public : LRUCache (int capacity) :cap (capacity){} int get (int key) { if (map.count (key)!=0 ) { int val = map[key]->second; list_cache.erase (map[key]); list_cache.push_front (make_pair (key,val)); map[key]=list_cache.begin (); return val; } return -1 ; } void put (int key, int value) { if (get (key) != -1 ) { list_cache.front () = make_pair (key,value); return ; } if (list_cache.size () == cap) { auto p = list_cache.back (); map.erase (p.first); list_cache.pop_back (); } list_cache.push_front (make_pair (key,value)); map[key]=list_cache.begin (); }private : int cap; list<pair<int ,int >> list_cache; unordered_map<int ,list<pair<int ,int >>::iterator> map; };struct DlinkNode { int key, value; DlinkNode* prev; DlinkNode* next; DlinkNode (): key (0 ), value (0 ), prev (nullptr ), next (nullptr ) {} DlinkNode (int _key, int _value): key (_key), value (_value), prev (nullptr ), next (nullptr ) {} };class LRUCache {private : unordered_map<int , DlinkNode*> cache; DlinkNode* head; DlinkNode* tail; int size; int capacity;public : LRUCache (int _capacity): capacity (_capacity), size (0 ) { head = new DlinkNode (); tail = new DlinkNode (); head->next = tail; tail->prev = head; } int get (int key) { if (!cache.count (key)) { return -1 ; } DlinkNode* node = cache[key]; moveToHead (node); return node->value; } void put (int key, int value) { if (!cache.count (key)) { DlinkNode* node = new DlinkNode (key, value); cache[key] = node; addToHead (node); ++size; if (size > capacity) { DlinkNode* removed = removeTail (); cache.erase (removed->key); delete removed; --size; } } else { DlinkNode* node = cache[key]; node->value = value; moveToHead (node); } } void addToHead (DlinkNode* node) { node->prev = head; node->next = head->next; head->next->prev = node; head->next = node; } void removeNode (DlinkNode* node) { node->prev->next = node->next; node->next->prev = node->prev; } void moveToHead (DlinkNode* node) { removeNode (node); addToHead (node); } DlinkNode* removeTail () { DlinkNode* node = tail->prev; removeNode (node); return node; } };