119 lines
2.2 KiB
Java
119 lines
2.2 KiB
Java
import java.util.HashMap;
|
|
|
|
class AllOne {
|
|
private class Node {
|
|
int freq;
|
|
Node prev, next;
|
|
Set<String> keys = new HashSet<>();
|
|
|
|
Node(int freq) {
|
|
this.freq = freq;
|
|
}
|
|
|
|
Node(int freq, Node prev, Node next) {
|
|
this.freq = freq;
|
|
|
|
this.prev = prev;
|
|
prev.next = this;
|
|
|
|
this.next = next;
|
|
next.prev = this;
|
|
}
|
|
|
|
void link(Map<String, Node> map, String key) {
|
|
keys.add(key);
|
|
map.put(key, this);
|
|
}
|
|
|
|
void remove() {
|
|
var prev = this.prev;
|
|
var next = this.next;
|
|
|
|
prev.next = next;
|
|
next.prev = prev;
|
|
}
|
|
}
|
|
|
|
Node head, tail;
|
|
Map<String, Node> map = new HashMap<>();
|
|
|
|
public AllOne() {
|
|
head = new Node(0);
|
|
tail = new Node(0);
|
|
|
|
head.next = tail;
|
|
tail.prev = head;
|
|
}
|
|
|
|
public void inc(String key) {
|
|
if (!map.containsKey(key)) {
|
|
var first = head.next;
|
|
if (first != tail && first.freq <= 1) {
|
|
first.link(map, key);
|
|
return;
|
|
}
|
|
|
|
var newNode = new Node(1, head, first);
|
|
newNode.link(map, key);
|
|
return;
|
|
}
|
|
|
|
var node = map.get(key);
|
|
var freq = node.freq;
|
|
node.keys.remove(key);
|
|
|
|
var next = node.next;
|
|
if (next != tail && next.freq == freq + 1) {
|
|
next.link(map, key);
|
|
} else {
|
|
var newNode = new Node(freq + 1, node, next);
|
|
newNode.link(map, key);
|
|
}
|
|
|
|
if (node.keys.isEmpty()) {
|
|
node.remove();
|
|
}
|
|
}
|
|
|
|
public void dec(String key) {
|
|
if (!map.containsKey(key)) {
|
|
return;
|
|
}
|
|
|
|
var node = map.get(key);
|
|
var freq = node.freq;
|
|
node.keys.remove(key);
|
|
|
|
if (freq == 1) {
|
|
map.remove(key);
|
|
} else {
|
|
var prev = node.prev;
|
|
if (prev != head && prev.freq == freq - 1) {
|
|
prev.link(map, key);
|
|
} else {
|
|
var newNode = new Node(freq - 1, prev, node);
|
|
newNode.link(map, key);
|
|
}
|
|
}
|
|
|
|
if (node.keys.isEmpty()) {
|
|
node.remove();
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|