请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。
实现 AllOne 类:
AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 “” 。
getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 “” 。
示例:
输入
[“AllOne”, “inc”, “inc”, “getMaxKey”, “getMinKey”, “inc”, “getMaxKey”, “getMinKey”]
[[], [“hello”], [“hello”], [], [], [“leet”], [], []]
输出
[null, null, null, “hello”, “hello”, null, “hello”, “leet”]
解释
AllOne allOne = new AllOne();
allOne.inc(“hello”);
allOne.inc(“hello”);
allOne.getMaxKey(); // 返回 “hello”
allOne.getMinKey(); // 返回 “hello”
allOne.inc(“leet”);
allOne.getMaxKey(); // 返回 “hello”
allOne.getMinKey(); // 返回 “leet”
提示:
1 <= key.length <= 10
key 由小写英文字母组成
测试用例保证:在每次调用 dec 时,数据结构中总存在 key
最多调用 inc、dec、getMaxKey 和 getMinKey 方法 5 * 104 次
class AllOne {/**定义node节点,双向链表,里面有cnt属性值记录次数,还有set集合保存key值, 用map存key与node的映射,当我们删除增加的时候,先寻找node左右是否有目标值,有的话就把key值存到目标节点的set中,没有则创建*/class Node {int cnt;Node left, right;Set<String> set = new HashSet<>();public Node(int cnt) {this.cnt = cnt;}}//如果key数量为0,就要删除掉这个节点public void clear(Node node) {if (node.set.size() == 0) {node.left.right = node.right;node.right.left = node.left;}}Node hh = new Node(-1), tt = new Node(-1);Map<String, Node> map = new HashMap<>();public AllOne() {hh.right = tt;tt.left = hh;}public void inc(String key) {//map中有该节点if (map.containsKey(key)) {Node node = map.get(key);//先删除set中的key值node.set.remove(key);Node next = null;//分情况,有目标节点和无目标节点if (node.right.cnt == node.cnt + 1) {next = node.right;} else {next = new Node(node.cnt + 1);//更改指针node.right.left = next;next.right = node.right;node.right = next;next.left = node;}next.set.add(key);//更新mapmap.put(key, next);clear(node);} else { //没有该节点Node node = null;if (hh.right.cnt == 1) {node = hh.right;} else {node = new Node(1);//更改指针node.left = hh;node.right = hh.right;hh.right.left = node;hh.right = node;}node.set.add(key);map.put(key, node);//不存在clear}}public void dec(String key) {//删除必定map中存在Node node = map.get(key);node.set.remove(key);Node pre = null;//说明只出现一次,那么删除后就没有key值,所以直接map删即可if (node.cnt == 1) {map.remove(key);} else {if (node.left.cnt == node.cnt - 1) {pre = node.left;} else {pre = new Node(node.cnt - 1);node.left.right = pre;pre.left = node.left;node.left = pre;pre.right = node;}pre.set.add(key);map.put(key, pre);}clear(node);}public String getMaxKey() {Node node = tt.left;//返回任意一个for (String s : node.set) return s;return "";}public String getMinKey() {Node node = hh.right;for (String s : node.set) return s;return "";}}/*** Your AllOne object will be instantiated and called as such:* AllOne obj = new AllOne();* obj.inc(key);* obj.dec(key);* String param_3 = obj.getMaxKey();* String param_4 = obj.getMinKey();*/
