|
| 1 | +# 432. All O`one Data Structure |
| 2 | +Design a data structure to store the strings' count with the ability to return the strings with minimum and maximum counts. |
| 3 | + |
| 4 | +Implement the `AllOne` class: |
| 5 | + |
| 6 | +* `AllOne()` Initializes the object of the data structure. |
| 7 | +* `inc(String key)` Increments the count of the string `key` by `1`. If `key` does not exist in the data structure, insert it with count `1`. |
| 8 | +* `dec(String key)` Decrements the count of the string `key` by `1`. If the count of `key` is `0` after the decrement, remove it from the data structure. It is guaranteed that `key` exists in the data structure before the decrement. |
| 9 | +* `getMaxKey()` Returns one of the keys with the maximal count. If no element exists, return an empty string `""`. |
| 10 | +* `getMinKey()` Returns one of the keys with the minimum count. If no element exists, return an empty string `""`. |
| 11 | + |
| 12 | +**Note** that each function must run in `O(1)` average time complexity. |
| 13 | + |
| 14 | +#### Example 1: |
| 15 | +<pre> |
| 16 | +<strong>Input:</strong> |
| 17 | +["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"] |
| 18 | +[[], ["hello"], ["hello"], [], [], ["leet"], [], []] |
| 19 | +<strong>Output:</strong> |
| 20 | +[null, null, null, "hello", "hello", null, "hello", "leet"] |
| 21 | +<strong>Explanation:</strong> |
| 22 | +AllOne allOne = new AllOne(); |
| 23 | +allOne.inc("hello"); |
| 24 | +allOne.inc("hello"); |
| 25 | +allOne.getMaxKey(); // return "hello" |
| 26 | +allOne.getMinKey(); // return "hello" |
| 27 | +allOne.inc("leet"); |
| 28 | +allOne.getMaxKey(); // return "hello" |
| 29 | +allOne.getMinKey(); // return "leet" |
| 30 | +</pre> |
| 31 | + |
| 32 | +#### Constraints: |
| 33 | +* `1 <= key.length <= 10` |
| 34 | +* `key` consists of lowercase English letters. |
| 35 | +* It is guaranteed that for each call to `dec`, `key` is existing in the data structure. |
| 36 | +* At most <code>5 * 10<sup>4</sup></code> calls will be made to `inc`, `dec`, `getMaxKey`, and `getMinKey`. |
| 37 | + |
| 38 | +## Solutions (Python) |
| 39 | + |
| 40 | +### 1. Solution |
| 41 | +```Python |
| 42 | +class AllOne: |
| 43 | + |
| 44 | + def __init__(self): |
| 45 | + self.keys = [] |
| 46 | + self.count = {} |
| 47 | + self.index = {} |
| 48 | + self.range = {} |
| 49 | + |
| 50 | + def inc(self, key: str) -> None: |
| 51 | + if key not in self.count: |
| 52 | + self.keys.append(key) |
| 53 | + self.count[key] = 1 |
| 54 | + self.index[key] = len(self.keys) - 1 |
| 55 | + if 1 not in self.range: |
| 56 | + self.range[1] = [self.index[key], self.index[key]] |
| 57 | + self.range[1][1] = self.index[key] |
| 58 | + else: |
| 59 | + count0 = self.count[key] |
| 60 | + count1 = count0 + 1 |
| 61 | + i = self.range[count0][0] |
| 62 | + j = self.index[key] |
| 63 | + self.index[self.keys[i]], self.index[self.keys[j]] = j, i |
| 64 | + self.keys[i], self.keys[j] = self.keys[j], self.keys[i] |
| 65 | + self.count[key] += 1 |
| 66 | + self.range[count0][0] += 1 |
| 67 | + if self.range[count0][0] > self.range[count0][1]: |
| 68 | + self.range.pop(count0) |
| 69 | + if count1 not in self.range: |
| 70 | + self.range[count1] = [i, i] |
| 71 | + self.range[count1][1] = i |
| 72 | + |
| 73 | + def dec(self, key: str) -> None: |
| 74 | + if self.count[key] == 1: |
| 75 | + self.index[self.keys[-1]] = self.index[key] |
| 76 | + self.keys[self.index[key]] = self.keys[-1] |
| 77 | + self.keys.pop() |
| 78 | + self.count.pop(key) |
| 79 | + self.index.pop(key) |
| 80 | + self.range[1][1] -= 1 |
| 81 | + if self.range[1][0] > self.range[1][1]: |
| 82 | + self.range.pop(1) |
| 83 | + else: |
| 84 | + count0 = self.count[key] |
| 85 | + count1 = count0 - 1 |
| 86 | + i = self.range[count0][1] |
| 87 | + j = self.index[key] |
| 88 | + self.index[self.keys[i]], self.index[self.keys[j]] = j, i |
| 89 | + self.keys[i], self.keys[j] = self.keys[j], self.keys[i] |
| 90 | + self.count[key] -= 1 |
| 91 | + self.range[count0][1] -= 1 |
| 92 | + if self.range[count0][0] > self.range[count0][1]: |
| 93 | + self.range.pop(count0) |
| 94 | + if count1 not in self.range: |
| 95 | + self.range[count1] = [i, i] |
| 96 | + self.range[count1][0] = i |
| 97 | + |
| 98 | + def getMaxKey(self) -> str: |
| 99 | + return self.keys[0] if self.keys != [] else "" |
| 100 | + |
| 101 | + def getMinKey(self) -> str: |
| 102 | + return self.keys[-1] if self.keys != [] else "" |
| 103 | + |
| 104 | + |
| 105 | +# Your AllOne object will be instantiated and called as such: |
| 106 | +# obj = AllOne() |
| 107 | +# obj.inc(key) |
| 108 | +# obj.dec(key) |
| 109 | +# param_3 = obj.getMaxKey() |
| 110 | +# param_4 = obj.getMinKey() |
| 111 | +``` |
0 commit comments