-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathDesignHashMap.kt
141 lines (130 loc) · 4.6 KB
/
DesignHashMap.kt
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
141
package questions
import _utils.UseCommentAsDocumentation
import questions.common.ClassInvoker
import utils.shouldBe
/**
* Design a HashMap without using any built-in hash table libraries:
* * `MyHashMap()` initializes the object with an empty map.
* * `void put(int key, int value)` inserts a (key, value) pair into the HashMap. If the key already exists in the map, update the corresponding value.
* * `int get(int key)` returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key.
* * `void remove(key)` removes the key and its corresponding value if the map contains the mapping for the key.
*
* [Source](https://leetcode.com/problems/design-hashmap/)
*
* @see MyHashSet
*/
@UseCommentAsDocumentation
class MyHashMap {
private var array = Array<Node?>(10) { null }
fun put(key: Int, value: Int) {
val index = getHashCode(key)
val (parent, self) = findParentAndSelf(index, key)
if (self != null) { // key already exists
self.value = value // then just update it
} else {
if (parent != null) { // append it to current bucket
parent.next = Node(key, value)
} else {
array[index] = Node(key, value) // no element in the current bucket so add it as first node
}
}
}
private fun findParentAndSelf(index: Int, key: Int): Pair<Node?, Node?> {
var current: Node? = array[index] ?: return null to null
if (current?.key == key) { // first item has the key
return null to current // so no parents
}
while (current != null) {
if (current.next?.key == key) { // next item has the key
return current to current.next
}
if (current.next == null) { // next item is null so last most item is the parent
return current to null
}
current = current.next
}
return current to null
}
private fun getHashCode(key: Int): Int {
return Integer.hashCode(key) % array.size // what is key is -ve, use abs?
}
fun get(key: Int): Int {
val index = getHashCode(key)
val (_, self) = findParentAndSelf(index, key)
return self?.value ?: -1
}
fun remove(key: Int) {
val index = getHashCode(key)
val (parent, self) = findParentAndSelf(index, key)
if (self == null) {
return
}
if (parent == null) { // this was the first node
array[index] = self.next
} else { // its parent exists so join it with the child
parent.next = self.next
}
}
inner class Node(val key: Int, var value: Int) {
var next: Node? = null
}
}
fun main() {
run {
MyHashMap().apply {
put(1, 1) // The map is now [[1,1]]
put(2, 2) // The map is now [[1,1], [2,2]]
get(1) shouldBe 1// return 1, The map is now [[1,1], [2,2]]
get(3) shouldBe -1 // return -1 (i.e., not found), The map is now [[1,1], [2,2]]
put(2, 1) // The map is now [[1,1], [2,1]] (i.e., update the existing value)
get(2) shouldBe 1// return 1, The map is now [[1,1], [2,1]]
remove(2) // remove the mapping for 2, The map is now [[1,1]]
get(2) shouldBe -1 // return -1 (i.e., not found), The map is now [[1,1]]
put(10, 5)
get(10) shouldBe 5
put(10, 6)
get(10) shouldBe 6
remove(10)
get(10) shouldBe -1
}
}
run {
MyHashMap().apply {
for (j in 1..50) {
val i = j * 9
remove(i)
get(i) shouldBe -1
put(i, i * 2)
get(i) shouldBe i * 2
put(i, i * 3)
get(i) shouldBe i * 3
remove(i)
get(i) shouldBe -1
put(i, i)
get(i) shouldBe i
}
}
}
run {
val invoker = ClassInvoker<IntArray, IntArray>(
listOf("MyHashMap", "remove", "get", "put", "put", "put", "get", "put", "put", "put", "put"),
) {
it
}
invoker.invoke(
listOf(
intArrayOf(),
intArrayOf(14),
intArrayOf(4),
intArrayOf(7, 3),
intArrayOf(11, 1),
intArrayOf(12, 1),
intArrayOf(7),
intArrayOf(1, 19),
intArrayOf(0, 3),
intArrayOf(1, 8),
intArrayOf(2, 6)
)
)
}
}