146. LRU 缓存机制

https://leetcode-cn.com/problems/lru-cache/
关键点在于每次的挪动,删除,增加的操作要记得同时更新哈希表和链表
LRU:

  1. key-value的保存,O(1) search, then HashMap - > key-ListNode(value)
  2. Double LinkedList, first in will be put in the front
    1. add a node at the end ( the latest used one and new coming)
    2. delete a node from the front ( full capacity)
    3. move a random node at the end ( refresh a node)

What do we need?

  1. class LinkedList - > key, value, next, prev
  2. a HashMap -> key - ListNode(key,value)
  3. def get - > if not in HashMap, return -1, if in HashMap, (1) refresh the corresponding key’s value in the HashMap (2) move the key to the tail of LinkedList, at the end return the value
  4. def put ->
    if in HashMap -> move it to the tail of LinkedList,
    if not in HashMap -> if capacity full, remove head.next from HashMap and remove head.next from LinkedList, then add the new one to HashMap, add the new one to the tail of LinkedList ```python class ListNode: def init(self,key=None, val=None):
    1. self.key=key
    2. self.val=val
    3. self.next = None
    4. self.prev = None

class LRUCache:

  1. def __init__(self, capacity: int):
  2. self.HashMap = {}
  3. self.capacity = capacity
  4. self.head = ListNode()
  5. self.tail = ListNode()
  6. self.head.next, self.tail.prev = self.tail, self.head
  7. def move_to_tail(self, key):
  8. # 从自己所在位置拿出来
  9. node = self.HashMap[key]
  10. node.prev.next = node.next
  11. node.next.prev = node.prev
  12. # 放到tail之前
  13. self.add_to_tail(node)
  14. def remove_from_head(self):
  15. # delete from HashMap
  16. # 链表里存了key就为了这个时候反向定位,从hashmap弹出
  17. self.HashMap.pop(self.head.next.key)
  18. # delete from the LinkList
  19. self.head.next = self.head.next.next
  20. self.head.next.prev = self.head
  21. def add_to_tail(self, node):
  22. # node 的前后
  23. node.prev = self.tail.prev
  24. node.next = self.tail
  25. # assign node to its prev's next and next's prev
  26. self.tail.prev.next = node
  27. self.tail.prev = node
  28. def get(self, key: int) -> int:
  29. if key not in self.HashMap:
  30. return -1
  31. else:
  32. self.move_to_tail(key)
  33. return self.HashMap[key].val
  34. def put(self, key: int, value: int) -> None:
  35. if key in self.HashMap:
  36. self.HashMap[key].val = value # update HashMap
  37. self.move_to_tail(key) # update the LinkedList
  38. else:
  39. if len(self.HashMap)==self.capacity: # check capacity
  40. self.remove_from_head()
  41. newNode = ListNode(key,value)
  42. self.HashMap[key]=newNode
  43. self.add_to_tail(newNode)
  1. <a name="5CKDu"></a>
  2. #### [716. 最大栈](https://leetcode-cn.com/problems/max-stack/)
  3. [https://leetcode-cn.com/problems/max-stack/](https://leetcode-cn.com/problems/max-stack/)<br />两个栈解决,time complexity O(n)<br />每次两个栈都压入,区别是max_stack是用来存放当前stack里最大value的,如果push的value大于max_stack[-1],那么压入value, 如果小于,那么把max_stack[-1]再压入一次
  4. ```python
  5. class MaxStack:
  6. def __init__(self):
  7. """
  8. initialize your data structure here.
  9. """
  10. self.stack = []
  11. self.max_stack = []
  12. def push(self, x: int) -> None:
  13. self.stack.append(x)
  14. if not self.max_stack:
  15. self.max_stack.append(x)
  16. else:
  17. self.max_stack.append(max(self.max_stack[-1],x))
  18. def pop(self) -> int:
  19. if self.stack:
  20. self.max_stack.pop()
  21. return self.stack.pop()
  22. else:
  23. return -1
  24. def top(self) -> int:
  25. return self.stack[-1]
  26. def peekMax(self) -> int:
  27. return self.max_stack[-1]
  28. def popMax(self) -> int:
  29. tmp = []
  30. while self.stack and self.stack[-1]!=self.max_stack[-1]:
  31. tmp.append(self.stack.pop())
  32. self.max_stack.pop()
  33. res = self.stack.pop()
  34. self.max_stack.pop()
  35. while tmp:
  36. self.push(tmp.pop())
  37. return res

难点在于popMax(), O(logN)需要用到二叉搜索树+双向链表

实现哈希表
https://leetcode-cn.com/problems/design-hashmap/

  1. class LinkedNode:
  2. def __init__(self, key=0,val=0, next=None):
  3. self.key = key
  4. self.val = val
  5. self.next = next
  6. class HashMap:
  7. def __init__(self):
  8. self.capacity = 1<<3
  9. self.loader_factor = 0.75
  10. self.arr = [None]*self.capacity
  11. self.count = 0
  12. def reset(self):
  13. self.capacity = self.capacity << 1
  14. self.tmp_arr = self.arr[:]
  15. self.arr = [None]*self.capacity
  16. for node in self.tmp_arr:
  17. while node:
  18. self.put(node.key, node.value)
  19. node = node.next
  20. def get(self,key):
  21. hash_key = self.get_hash_key(key)
  22. if self.arr[hash_key]:
  23. head = self.arr[hash_key]
  24. while head:
  25. if head.key == key:
  26. return head.val
  27. head = head.next
  28. # if not find
  29. return
  30. def get_hash_key(self, key):
  31. return key & (self.capacity -1)
  32. def put(self,key,value):
  33. if self.count > self.capacity*self.loader_factor:
  34. self.reset()
  35. hash_key = self.get_hash_key(key)
  36. if not self.arr[hash_key]:
  37. self.arr[hash_key] = LinkedNode(key=key,val=value)
  38. self.count+=1
  39. else:
  40. head = self.arr[hash_key]
  41. while head:
  42. if head.key == key:
  43. head.val = value
  44. break
  45. if not head.next:
  46. head.next = LinkedNode(key=key,val=value)
  47. self.count+=1
  48. head = head.next

实现堆排序

  • 堆排序是利用 进行排序的
  • 是一种完全二叉树
  • 有两种类型: 大根堆 小根堆
  • 两种类型的概念如下:
    大根堆:每个结点的值都大于或等于左右孩子结点
    小根堆:每个结点的值都小于或等于左右孩子结点

image.png
Find the maximum element and place the maximum element at the end.
a binary heap is a complete binary tree.

  1. build a max heap from the input data
  2. at this point, the largest item is stored at the root of the heap, replace it with the last item of the heap followed by reducing the size of heap by 1. finally heapify the root of the tree.
  3. repeat step 2 while size of heap is greater than 1.

    1. import time
    2. def heapify(arr,n, i):
    3. largest = i
    4. l = i*2 + 1
    5. r = i*2 + 2
    6. if l < n and arr[largest] < arr[l]:
    7. largest = l
    8. if r < n and arr[largest] < arr[r]:
    9. largest = r
    10. if largest!=i:
    11. arr[largest], arr[i] = arr[i], arr[largest]
    12. heapify(arr,n,largest)
    13. def heapSort(arr):
    14. n = len(arr)
    15. for i in range(n//2-1, -1, -1):
    16. heapify(arr, n, i)
    17. for i in range(n-1, 0,-1):
    18. arr[i], arr[0] = arr[0], arr[i]
    19. # heapify until i, because the rest have been sorted and removed from the heap
    20. heapify(arr,i,0)
    21. return arr