Design HashMap
Design a?HashMap?without using any built-in hash table libraries.?To be specific, your design should include these functions:
- put(key, value):?Insert a?(key,value)?pair into the?HashMap. If the value already exists in the?HashMap, update the value.
- get(key): Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the?key.
- remove(key)?:?Remove the mapping for the value?key?if this map contains the mapping for the?key.
Example:
MyHashMap hashMap = new MyHashMap();
hashMap.put(1, 1); ? ? ? ? ?
hashMap.put(2, 2); ? ? ? ?
hashMap.get(1); ? ? ? ? // returns 1
hashMap.get(3); ? ? ? ? // returns -1 (not found)
hashMap.put(2, 1); ? ? ?// update the existing value
hashMap.get(2); ? ? ? ? // returns 1
hashMap.remove(2); ? ? ?// remove the mapping for 2
hashMap.get(2); ? ? ? ? // returns -1 (not found)
Note:
- All keys and values will be in the range of?[0, 1000000].
- The number of operations will be in the range of?[1, 10000].
- Please do not use the built-in HashMap library.
Solution : Traditional HashMap Implementation – Using an Array of LinkedList
1. The general implementation of?HashMap?uses?bucket?which is basically a?chain of linked lists?and each node containing?<key,value>?pair.
2. So if we have duplicate nodes, that doesn’t matter – it will still replicate each key with its value in the linked list node.
3. When we insert the pair?(10,20)?and then?(10,30), there is technically no collision involved. We are just replacing the old value with the new value for a given key?10, since in both cases,?10?is equal to?10?and also the hash code for?10?is always?10.
4. The collision happens when multiple keys hash to the same?bucket. In that case, we need to make sure that we can distinguish between those keys.?Chaining collision resolution?is one of those techniques which is used for this.
5. Just for the information. In JDK 8,?HashMap?has been tweaked so that if keys can be compared for ordering, then any densely-populated?bucket?is implemented as a?tree, so that even if there are lots of entries with the same hash-code, the complexity is?O(log n).
Time complexity :?O(1)?average and?O(n)?worst case – for all?get(), put()?and?remove()?methods.
Space complexity :?O(n)?– where?n?is the number of entries in?HashMap.
class ListNode
????int key;
????int value;
????ListNode next;
?????
????public ListNode(int k, int v){
????????this.key = k;
????????this.value = v;
????}
}
?
class MyHashMap {
?
????private ListNode[] data = null;
?????
????/** Initialize your data structure here. */
????public MyHashMap() {
????????data = new ListNode[10000];
????}
?????
????/** value will always be non-negative. */
????public void put(int key, int value) {
????????int bucketNo = hash(key);
????????ListNode head = data[bucketNo];
????????ListNode node = new ListNode(key, value);
????????if(head == null){
????????????data[bucketNo] = node;
????????????return;
????????}
????????if(head.key == key){
????????????head.value = value;
????????????return;
????????}
????????ListNode prev = head;
????????ListNode current = head.next;
????????while(current != null){
????????????if(current.key == key){
????????????????current.value = value;
????????????????return;
????????????}
????????????current = current.next;
????????????prev = prev.next;
????????}
????????prev.next = node;
????????return;
????}
?????
????/** Returns the value to which the specified key is mapped,
?????or -1 if this map contains no mapping for the key */
????public int get(int key) {
????????int bucketNo = hash(key);
????????ListNode head = data[bucketNo];
????????ListNode current = head;
????????int result = -1;
????????while(current != null){
????????????if(current.key == key){
????????????????result = current.value;
????????????????break;
????????????}
????????????current = current.next;
????????}
????????return result;
????}
?????
????/** Removes the mapping of the specified value key
?????if this map contains a mapping for the key */
????public void remove(int key) {
????????int bucketNo = hash(key);
????????ListNode head = data[bucketNo];
????????if(head == null){
????????????return;
????????}
????????if(head.key == key){
????????????data[bucketNo] = head.next;
????????}
????????ListNode prev = head;
????????ListNode current = head.next;
????????while(current != null && current.next != null){
????????????if(current.key == key){
????????????????prev.next = current.next;
????????????????return;
????????????}
????????????prev = prev.next;
????????????current = current.next;
????????}
????????// when we are removing the last node of the LinkedList
????????if(current != null && current.key == key){
????????????prev.next = null;
????????}
????????return;
????}
?????
????private int hash(int key){
????????return (key % data.length);
????}
}
?
/**
?* Your MyHashMap object will be instantiated and called as such:
?* MyHashMap obj = new MyHashMap();
?* obj.put(key,value);
?* int param_2 = obj.get(key);
?* obj.remove(key);
?*/{