Leetcode Data Structure Design Problem Set (1)
- 146.LRU Cache
- 284.Peeking Iterator
- 341.Flatten Nested List Iterator
- 295.Find Median from Data Stream
146. LRU Cache
Design Least Recently Used (LRU) Cache
Use double-linked list as cache, disconnect the old node and reconnect it to the tail of the list when get
an value. add new node to the tail and drop the first (the least used) node if exceed capacity.
use a dictionary to log {key: node}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
56class Node:
def __init__(self, k=0, v=0):
self.k = k
self.v = v
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
self.dict = {}
self.cap = capacity
def _remove(self, node):
# remove the least used node
node.prev.next = node.next
node.next.prev = node.prev
def _add(self, node):
last = self.tail.prev
self.tail.prev = node
last.next = node
node.next = self.tail
node.prev = last
def get(self, key: int) -> int:
if key not in self.dict:
return -1
# move recent used node to tail
node = self.dict[key]
self._remove(node)
self._add(node)
return node.v
def put(self, key: int, value: int) -> None:
# remove the existed key first, we will add new anyway
if key in self.dict:
node = self.dict[key]
self._remove(node)
del self.dict[key]
node = Node(key, value)
self._add(node)
self.dict[key] = node
if len(self.dict) > self.cap:
least = self.head.next
self._remove(least)
del self.dict[least.k]
284. Peeking Iterator
My initial idea was create a one-way linked list, or initialize a normal list, which is too easy. But if so, it lose the meaning as iterator. Then I second thought, I don’t even need a list, I just need a buffer for the peak value.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
37class PeekingIterator:
def __init__(self, iterator):
"""
Initialize your data structure here.
:type iterator: Iterator
"""
self._iterator = iterator
self._peak = None
def peek(self):
"""
Returns the next element in the iteration without advancing the iterator.
:rtype: int
"""
if not self._peak and self._iterator.hasNext():
self._peak = self._iterator.next()
return self._peak
def next(self):
"""
:rtype: int
"""
if self._peak:
peak = self._peak
self._peak = None
return peak
return self._iterator.next()
def hasNext(self):
"""
:rtype: bool
"""
if self._peak:
return True
return self._iterator.hasNext()
341. Flatten Nested List Iterator
Flatten nested list in init. Use deque to faster pop the first element.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class NestedIterator:
def __init__(self, nestedList: [NestedInteger]):
self.ls = deque()
self.flatten(nestedList)
def flatten(self, nestedList):
for l in nestedList:
if l.isInteger():
self.ls.append(l.getInteger())
else:
self.flatten(l.getList())
def next(self) -> int:
return self.ls.popleft() if self.hasNext else None
def hasNext(self) -> bool:
return len(self.ls) > 0
295. Find Median from Data Stream
Dividing data into 2 heaps (length as equal as possible):
- Use max heap to store a chunk of smaller elements
- Use min heap to store another chunk of larger elements.
Reference:
https://mp.weixin.qq.com/s/oklQN_xjYy--_fbFkd9wMg
1 | import heapq |