In [28]:
class AllOne:
    def __init__(self):
        self.counts = {} #str -> number of instances
        self.strings = {} #number of instance -> set of strings
        self.max = 0 # number of max instances of a string in counts 
        self.min = 0 # number of min instances of a string in counts 
        
    def inc(self, s: str) -> None:
        if s in self.counts:
            # update self.min and self.max
            if s in self.strings[self.max]:
                self.max +=1
            self.strings[self.counts[s]].remove(s)
            if self.strings[self.min] == set(): # then s was the unique min val
                self.min += 1

            # update self.strings and self.counts
            if self.strings[self.counts[s]] == set():
                del self.strings[self.counts[s]]
            self.counts[s] += 1
            if self.counts[s] in self.strings:
                self.strings[self.counts[s]].add(s)
            else:
                self.strings[self.counts[s]] = {s}

        else:
            if self.min == 0: # no strings so far
                self.max = 1
            self.min = 1
            
            self.counts[s] = 1
            if 1 in self.strings:
                self.strings[1].add(s)
            else: 
                self.strings[1] = {s}

    def dec(self, s: str) -> None:
        self.strings[self.counts[s]].remove(s)
        if self.strings[self.max] == set(): #removed only max val
            self.max -= 1
        if self.counts[s] == self.min:
            self.min -= 1

        if self.strings[self.counts[s]] == set():
                del self.strings[self.counts[s]]
        if self.min == 0 and self.strings != {}:
            empty = True
            i=1
            while empty:
                if i in self.strings:
                    self.min = i
                    empty = False
                i += 1
            
        self.counts[s] -= 1
        if self.counts[s] == 0:
            del self.counts[s]

        else:
            if self.counts[s] in self.strings:
                self.strings[self.counts[s]].add(s)
            else:
                self.strings[self.counts[s]] = {s}
                
        
    def getMaxKey(self) -> str:
        if self.max == 0:
            return ""
        else:
            return next(iter(self.strings[self.max]))
            
    def getMinKey(self) -> str:
        if self.min == 0:
            return ""
        else:
            return next(iter(self.strings[self.min]))
In [29]:
allOne = AllOne()
allOne.inc("hello")
allOne.inc("hello")
print(allOne.getMaxKey())
print(allOne.getMinKey())
allOne.inc("leet")
print(allOne.getMaxKey())
print(allOne.getMinKey())
# hello hello hello leet
hello
hello
hello
leet
In [ ]: