-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy path432. All One Data Structure.java
executable file
·123 lines (103 loc) · 3.88 KB
/
432. All One Data Structure.java
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
H
tags: Design, Doubly Linked List
time: O(1)
space: O(n)
#### Doubly Linked List
- IMPORTANT: the problem aims to put keys of same frequency in same node! This affects the design of node
- Main a class `Node {keySet, count, last/next pointers}`
- Each operation:
- 1) finds target node and extract the key
- 2) calculate: count +/- 1
- 3) find new spot to store the key (prior positions or later positions)
- Be careful when handling the cases in inc() and dec()
```
/*
Implement a data structure supporting the following operations:
Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty string.
Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string.
GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "".
GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "".
*/
class AllOne {
class Node {
Node last, next;
Set<String> keys = new HashSet<>();
int count;
public Node(int count, String key) {
this.count = count;
this.keys.add(key);
}
}
Map<String, Node> map;
Node head, tail; // Doubly Linked List
/** Initialize your data structure here. */
public AllOne() {
map = new HashMap<>();
head = new Node(-1, "");
tail = new Node(-1, "");
head.next = tail;
tail.last = head;
}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
public void inc(String key) {
// Find node to process; use head if not exist
Node node = map.getOrDefault(key, head);
int count = removeKey(key) + 1;
// Insert new node or populate existing node
if (node.next.count != count) insert(node, node.next, new Node(count, key));
else node.next.keys.add(key);
map.put(key, node.next);
// Clean up
if (node.keys.isEmpty()) remove(node);
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
public void dec(String key) {
if (!map.containsKey(key)) return;
Node node = map.get(key);
int count = removeKey(key) - 1;
if (count == 0) { // reduce to 0, delete
map.remove(key);
} else { // Insert new node or populate existing node
if (node.last.count != count) insert(node.last, node, new Node(count, key));
else node.last.keys.add(key);
map.put(key, node.last);
}
if (node.keys.isEmpty()) remove(node);
}
/** Returns one of the keys with maximal value. */
public String getMaxKey() {
if (map.isEmpty()) return "";
return tail.last.keys.iterator().next();
}
/** Returns one of the keys with Minimal value. */
public String getMinKey() {
if (map.isEmpty()) return "";
return head.next.keys.iterator().next();
}
// Helper Functions
private void remove(Node node) {
node.last.next = node.next;
node.next.last = node.last;
}
private int removeKey(String key) {
if (!map.containsKey(key)) return 0;
Node node = map.get(key);
node.keys.remove(key);
return node.count;
}
private void insert(Node last, Node next, Node newNode) {
newNode.next = next;
next.last = newNode;
last.next = newNode;
newNode.last = last;
}
}
/**
* 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();
*/
```