-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAllOne.java
More file actions
140 lines (111 loc) · 3.04 KB
/
AllOne.java
File metadata and controls
140 lines (111 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
class AllOne {
private Map<Integer, LinkedHashSet<String>> count2Key;
private Map<String, Node> key2Count;
private Node first, last;
private class Node {
private int data;
private Node next;
private Node pre;
private Node(int data) {
this.data = data;
this.next = null;
this.pre = null;
}
private Node(Node pre, int data, Node next) {
this.pre = pre;
this.data = data;
this.next = next;
}
}
public AllOne() {
this.count2Key = new HashMap<>();
this.key2Count = new HashMap<>();
this.first = new Node(0);
this.last = new Node(Integer.MAX_VALUE);
this.first.next = this.last;
this.last.pre = this.first;
}
public void inc(String key) {
Node node = key2Count.getOrDefault(key, first);
int count = node.data;
// insert new count
key2Count.put(key, findNextNode(node));
count2Key.computeIfAbsent(count + 1, c -> new LinkedHashSet<>()).add(key);
// remove origin count
LinkedHashSet<String> originSet = count2Key.get(count);
if (originSet != null) {
originSet.remove(key);
if (originSet.isEmpty()) {
count2Key.remove(count);
removeNode(node);
}
}
}
public void dec(String key) {
Node node = key2Count.get(key);
if (node == null) {
return;
}
int count = node.data;
if (count == 1) {
// remove key
key2Count.remove(key);
} else {
// insert new count
key2Count.put(key, findPreNode(node));
count2Key.computeIfAbsent(count - 1, c -> new LinkedHashSet<>()).add(key);
}
// remove origin count
LinkedHashSet<String> originSet = count2Key.get(count);
if (originSet != null) {
originSet.remove(key);
if (originSet.isEmpty()) {
count2Key.remove(count);
removeNode(node);
}
} else {
throw new IllegalStateException("origin set can not be null");
}
}
public String getMaxKey() {
int count = last.pre.data;
LinkedHashSet<String> keySet = count2Key.get(count);
if (keySet == null) {
return "";
}
return keySet.stream().findFirst().get();
}
public String getMinKey() {
int count = first.next.data;
LinkedHashSet<String> keySet = count2Key.get(count);
if (keySet == null) {
return "";
}
return keySet.stream().findFirst().get();
}
private Node findNextNode(Node node) {
if (node.next.data == node.data + 1) {
return node.next;
}
Node insertNode = new Node(node, node.data + 1, node.next);
node.next.pre = insertNode;
node.next = insertNode;
return insertNode;
}
private Node findPreNode(Node node) {
if (node.pre.data == node.data - 1) {
return node.pre;
}
Node insertNode = new Node(node.pre, node.data - 1, node);
node.pre.next = insertNode;
node.pre = insertNode;
return insertNode;
}
private void removeNode(Node node) {
node.pre.next = node.next;
node.next.pre = node.pre;
}
}