Skip to content

Commit f615c90

Browse files
committed
[Design] Add a solution to All O`one Data Structure
1 parent 07e16a4 commit f615c90

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

Design/AllOne.swift

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/**
2+
* Question Link: https://leetcode.com/problems/all-oone-data-structure/
3+
* Primary idea: Use a doubly linked list while the node is val and all keys, and
4+
* a hash table where value is the node containing the key
5+
* Time Complexity: O(1), Space Complexity: O(n)
6+
*
7+
*/
8+
9+
class AllOne {
10+
11+
private var dict: [String: Node]
12+
13+
private var head: Node
14+
private var tail: Node
15+
16+
/** Initialize your data structure here. */
17+
init() {
18+
dict = [String: Node]()
19+
20+
head = Node(-1, "")
21+
tail = Node(-1, "")
22+
head.post = tail
23+
tail.prev = head
24+
}
25+
26+
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
27+
func inc(_ key: String) {
28+
if let node = dict[key] {
29+
update(node, key, 1)
30+
} else {
31+
if head.post!.val != 1 {
32+
let node = Node(1, key)
33+
insert(node, after: head)
34+
dict[key] = node
35+
} else {
36+
head.post!.list.insert(key)
37+
dict[key] = head.post!
38+
}
39+
}
40+
}
41+
42+
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
43+
func dec(_ key: String) {
44+
guard let node = dict[key] else {
45+
return
46+
}
47+
48+
update(node, key, -1)
49+
}
50+
51+
/** Returns one of the keys with maximal value. */
52+
func getMaxKey() -> String {
53+
if dict.count > 0 {
54+
return tail.prev!.list.first!
55+
} else {
56+
return ""
57+
}
58+
}
59+
60+
/** Returns one of the keys with Minimal value. */
61+
func getMinKey() -> String {
62+
if dict.count > 0 {
63+
return head.post!.list.first!
64+
} else {
65+
return ""
66+
}
67+
}
68+
69+
private func update(_ node: Node, _ key: String, _ addVal: Int) {
70+
node.list.remove(key)
71+
72+
let next = addVal == 1 ? node.post : node.prev
73+
74+
// insert new node
75+
if next!.val != node.val + addVal {
76+
guard node.val + addVal != 0 else {
77+
dict[key] = nil
78+
79+
removeIfNecessary(node)
80+
81+
return
82+
}
83+
84+
let newNode = Node(node.val + addVal, key)
85+
86+
if addVal == 1 {
87+
insert(newNode, after: node)
88+
} else {
89+
insert(newNode, before: node)
90+
}
91+
92+
dict[key] = newNode
93+
94+
// insert key to next node
95+
} else {
96+
next!.list.insert(key)
97+
dict[key] = next
98+
}
99+
100+
removeIfNecessary(node)
101+
}
102+
103+
private func insert(_ newNode: Node, after node: Node) {
104+
node.post?.prev = newNode
105+
newNode.post = node.post
106+
107+
newNode.prev = node
108+
node.post = newNode
109+
}
110+
111+
private func insert(_ newNode: Node, before node: Node) {
112+
node.prev?.post = newNode
113+
newNode.prev = node.prev
114+
115+
newNode.post = node
116+
node.prev = newNode
117+
}
118+
119+
private func removeIfNecessary(_ node: Node) {
120+
guard node.list.isEmpty else {
121+
return
122+
}
123+
124+
node.post!.prev = node.prev
125+
node.prev!.post = node.post
126+
127+
node.prev = nil
128+
node.post = nil
129+
130+
}
131+
}
132+
133+
fileprivate class Node {
134+
var val: Int
135+
var list: Set<String>
136+
var prev: Node?
137+
var post: Node?
138+
139+
init(_ val: Int, _ key: String) {
140+
self.val = val
141+
list = Set<String>([key])
142+
}
143+
}
144+
145+
/**
146+
* Your AllOne object will be instantiated and called as such:
147+
* let obj = AllOne()
148+
* obj.inc(key)
149+
* obj.dec(key)
150+
* let ret_3: String = obj.getMaxKey()
151+
* let ret_4: String = obj.getMinKey()
152+
*/

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
![Leetcode](./logo.png?style=centerme)
55

66
## Progress
7-
[Problem Status](#problem-status) shows the latest progress to all 1000+ questions. Currently we have 311 completed solutions. Note: questions with &hearts; mark means that you have to **Subscript to premium membership** of LeetCode to unlock them.
7+
[Problem Status](#problem-status) shows the latest progress to all 1000+ questions. Currently we have 312 completed solutions. Note: questions with &hearts; mark means that you have to **Subscript to premium membership** of LeetCode to unlock them.
88

99
## Contributors
1010

@@ -397,6 +397,7 @@
397397
[Add and Search Word - Data structure design](https://leetcode.com/problems/add-and-search-word-data-structure-design/)| [Swift](./Design/AddSearchWord.swift)| Medium | O(24^n)| O(n)|
398398
[Insert Delete GetRandom O(1)](https://leetcode.com/problems/insert-delete-getrandom-o1/)| [Swift](./Design/InsertDeleteGetRandom.swift)| Medium| O(1)| O(n)|
399399
[LRU Cache](https://leetcode.com/problems/lru-cache/)| [Swift](./Design/LRUCache.swift)| Hard| O(1)| O(n)|
400+
[All O`one Data Structure](https://leetcode.com/problems/all-oone-data-structure/)| [Swift](./Design/AllOne.swift)| Hard| O(1)| O(n)|
400401

401402

402403
## Google

0 commit comments

Comments
 (0)