mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
202 lines
5.8 KiB
Python
202 lines
5.8 KiB
Python
class node:
|
|
def __init__(self,val=None,data_mp=None,pre=None,next=None):
|
|
self.val=val
|
|
self.data_mp = {} if data_mp is None else data_mp
|
|
self.pre=pre
|
|
self.next=next
|
|
def __lt__(self,nd):
|
|
return self.val<nd.val
|
|
def getOne(self):
|
|
if not self.data_mp:
|
|
return ''
|
|
else:return list(self.data_mp.items())[0][0]
|
|
def __getitem__(self,key):
|
|
return self.data_mp[key]
|
|
def __iter__(self):
|
|
return iter(self.data_mp)
|
|
def __delitem__(self,key):
|
|
del self.data_mp[key]
|
|
def __setitem__(self,key,val):
|
|
self.data_mp[key]= val
|
|
def isEmpty(self):
|
|
return self.data_mp=={}
|
|
def __repr__(self):
|
|
return 'node({},{})'.format(self.val,self.data_mp)
|
|
class doubleLinkedList:
|
|
def __init__(self):
|
|
self.head= self.tail = node(0)
|
|
self.head.next = self.head
|
|
self.head.pre = self.head
|
|
self.chain_mp={0:self.head}
|
|
def __str__(self):
|
|
li = list(self.chain_mp.values())
|
|
li = [str(i) for i in li]
|
|
return 'min:{}, max:{}\n'.format(self.head.val,self.tail.val) \
|
|
+ '\n'.join(li)
|
|
def getMax(self):
|
|
return self.tail.getOne()
|
|
def getMin(self):
|
|
return self.head.getOne()
|
|
def addIncNode(self,val):
|
|
# when adding a node,inc 1, so it's guranted that node(val-1) exists
|
|
self.chain_mp[val].pre= self.chain_mp[val-1]
|
|
self.chain_mp[val].next= self.chain_mp[val-1].next
|
|
self.chain_mp[val-1].next.pre = self.chain_mp[val-1].next = self.chain_mp[val]
|
|
def addDecNode(self,val):
|
|
# when adding a node,dec 1, so it's guranted that node(val+1) exists
|
|
self.chain_mp[val].next= self.chain_mp[val+1]
|
|
self.chain_mp[val].pre= self.chain_mp[val+1].pre
|
|
self.chain_mp[val+1].pre.next = self.chain_mp[val+1].pre = self.chain_mp[val]
|
|
def addNode(self,val,dec=False):
|
|
self.chain_mp[val] = node(val)
|
|
if dec:self.addDecNode(val)
|
|
else:self.addIncNode(val)
|
|
if self.tail.val<val:self.tail = self.chain_mp[val]
|
|
if self.head.val>val or self.head.val==0:self.head= self.chain_mp[val]
|
|
def delNode(self,val):
|
|
self.chain_mp[val].next.pre = self.chain_mp[val].pre
|
|
self.chain_mp[val].pre.next = self.chain_mp[val].next
|
|
if self.tail.val==val:self.tail = self.chain_mp[val].pre
|
|
if self.head.val==val:self.head = self.chain_mp[val].next
|
|
del self.chain_mp[val]
|
|
def incTo(self,key,val):
|
|
if val not in self.chain_mp:
|
|
self.addNode(val)
|
|
self.chain_mp[val][key] = val
|
|
if val!=1 : # key in the pre node
|
|
del self.chain_mp[val-1][key]
|
|
#print(self.chain_mp[val-1])
|
|
if self.chain_mp[val-1].isEmpty():
|
|
#print('*'*20)
|
|
self.delNode(val-1)
|
|
def decTo(self,key,val):
|
|
if val not in self.chain_mp:
|
|
self.addNode(val,dec=True)
|
|
# notice that the headnode(0) shouldn't add key
|
|
if val!=0: self.chain_mp[val][key] = val
|
|
del self.chain_mp[val+1][key]
|
|
if self.chain_mp[val+1].isEmpty():
|
|
self.delNode(val+1)
|
|
|
|
class AllOne:
|
|
def __init__(self):
|
|
"""
|
|
Initialize your data structure here.
|
|
"""
|
|
self.op = {"inc":self.inc,"dec":self.dec,"getMaxKey":self.getMaxKey,"getMinKey":self.getMinKey}
|
|
self.mp = {}
|
|
self.dll = doubleLinkedList()
|
|
def __str__(self):
|
|
return str(self.dll)
|
|
def __getitem__(self,key):
|
|
return self.mp[key]
|
|
def __delitem__(self,key):
|
|
del self.mp[key]
|
|
def __setitem__(self,key,val):
|
|
self.mp[key]= val
|
|
def __iter__(self):
|
|
return iter(self.mp)
|
|
def inc(self, key,n=1):
|
|
"""
|
|
Inserts a new key <Key> with value 1. Or increments an existing key by 1.
|
|
:type key: str
|
|
:rtype: void
|
|
"""
|
|
if key in self:
|
|
self[key]+=n
|
|
else:self[key]=n
|
|
for i in range(n): self.dll.incTo(key, self[key])
|
|
def dec(self, key,n=1):
|
|
"""
|
|
Decrements an existing key by 1. If Key's value is 1, remove it from the data structure.
|
|
:type key: str
|
|
:rtype: void
|
|
"""
|
|
if key in self.mp:
|
|
mn = min( self[key],n)
|
|
for i in range(mn): self.dll.decTo(key, self[key]-i-1)
|
|
if self[key] == n:
|
|
del self[key]
|
|
else:
|
|
self[key] = self[key]-n
|
|
def getMaxKey(self):
|
|
"""
|
|
Returns one of the keys with maximal value.
|
|
:rtype: str
|
|
"""
|
|
return self.dll.getMax()
|
|
|
|
def getMinKey(self):
|
|
"""
|
|
Returns one of the keys with Minimal value.
|
|
:rtype: str
|
|
"""
|
|
return self.dll.getMin()
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
ops=["inc","inc","inc","inc","inc","dec","dec","getMaxKey","getMinKey"]
|
|
data=[["a"],["b"],["b"],["b"],["b"],["b"],["b"],[],[]]
|
|
obj = AllOne()
|
|
for op,datum in zip(ops,data):
|
|
print(obj.op[op](*datum))
|
|
print(op,datum)
|
|
print(obj)
|
|
|
|
'''
|
|
None
|
|
inc ['a']
|
|
min:1, max:1
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
None
|
|
inc ['b']
|
|
min:1, max:1
|
|
node(0,{})
|
|
node(1,{'a': 1, 'b': 1})
|
|
None
|
|
inc ['b']
|
|
min:1, max:2
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(2,{'b': 2})
|
|
None
|
|
inc ['b']
|
|
min:1, max:3
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(3,{'b': 3})
|
|
None
|
|
inc ['b']
|
|
min:1, max:4
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(4,{'b': 4})
|
|
None
|
|
dec ['b']
|
|
min:1, max:3
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(3,{'b': 3})
|
|
None
|
|
dec ['b']
|
|
min:1, max:2
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(2,{'b': 2})
|
|
b
|
|
getMaxKey []
|
|
min:1, max:2
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(2,{'b': 2})
|
|
a
|
|
getMinKey []
|
|
min:1, max:2
|
|
node(0,{})
|
|
node(1,{'a': 1})
|
|
node(2,{'b': 2})
|
|
'''
|