请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。
实现 AllOne 类:
AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 "" 。
getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 "" 。
来源:力扣(LeetCode)
class AllOne {
// 双向链表按次数从小到大排序
Node head, tail;
// 哈希表保存 key->Node 的映射
Map<String, Node> map;
public AllOne() {
this.head = new Node(-1);
this.tail = new Node(10000000);
this.head.next = this.tail;
this.tail.prev = this.head;
this.map = new HashMap<>();
}
public void inc(String key) {
if (map.containsKey(key)) {
// 包含key的情况下
Node node = map.get(key);
Node next = node.next;
int newCount = node.count + 1;
// 如果下一节点的数量等于新数量
// 则key加入下一个节点
if (next.count == newCount) {
next.addKey(key);
map.put(key, next);
} else {
// 否则新建一个Node并插入到当前节点之后
Node newNode = new Node(key, newCount);
node.next(newNode);
map.put(key, newNode);
}
// 当前节点移除这个key
node.removeKey(key);
} else {
// 不包含这个key的情况下
// 直接看head的下一个节点的数量是不是1
Node head = this.head;
Node next = head.next;
if (next.count == 1) {
next.addKey(key);
map.put(key, next);
} else {
Node newNode = new Node(key, 1);
head.next(newNode);
map.put(key, newNode);
}
}
}
public void dec(String key) {
// 题目约定了一定包含这个key
Node node = map.get(key);
Node prev = node.prev;
int newCount = node.count - 1;
if (prev.count == newCount) {
prev.addKey(key);
map.put(key, prev);
} else if (newCount == 0){
map.remove(key);
} else {
Node newNode = new Node(key, newCount);
node.prev(newNode);
map.put(key, newNode);
}
node.removeKey(key);
}
public String getMaxKey() {
if (tail.prev == head) {
return "";
}
return tail.prev.keys.iterator().next();
}
public String getMinKey() {
if (head.next == tail) {
return "";
}
return head.next.keys.iterator().next();
}
static class Node {
int count;
Node next;
Node prev;
Set<String> keys;
Node(int count) {
this.count = count;
}
Node(String key, int count) {
this.keys = new HashSet<>();
this.keys.add(key);
this.count = count;
}
void addKey(String key) {
this.keys.add(key);
}
void removeKey(String key) {
this.keys.remove(key);
if (this.keys.isEmpty()) {
remove();
}
}
void next(Node next) {
// 在当前节点后面插入一个节点
Node nextnext = this.next;
this.next = next;
next.prev = this;
next.next = nextnext;
nextnext.prev = next;
}
void prev(Node prev) {
// 在当前节点前面插入一个节点
Node prevprev = this.prev;
this.prev = prev;
prev.next = this;
prev.prev = prevprev;
prevprev.next = prev;
}
void remove() {
// 删除当前节点
Node prev = this.prev;
Node next = this.next;
prev.next = next;
next.prev = prev;
}
}
}