In computing Hash Table or Hash Maps are amazing. For me it's the 9th wonder of the world. Compounding is still the 8th one 😄

So let's understand what is hashing.

Hashing

Hashing is the process of converting a given key into another value. A hash function is used to generate the new value according to a mathematical algorithm. The result of a hash function is known as a hash value or simply, a hash.

There are many theories behind hashing like one way hashing, two way hashing, collisions etc. but let's not dive too deep. That's for another day.

Any programming language has rich sets of APIs(not the REST API mind you 😁).

We usually have Lists, Maps, Sets etc. One such is Hash Map and Hash Table.

Both of them are used to save and retrieve data.

The time complexities are as follows:

• Search : O(1) 🔍
• Insert : O(1) ✔
• Delete : O(1) ❌

You can see why I am calling it the 9th wonder. O(1) is favorites of any programmers!

Okay, now let's focus on the problem in hand.

The Problem

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.

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]`.
• Do not use the built-in HashMap library.

Here we cannot use any in built libraries and so this makes it bit difficult. But the notes above will give us some hints. So the key and values are in confined range.

Let's see a JAVA implementation of the problem:

``````class MyOwnHashMap {

private int[] values;

/**
* Initialize the data structure here.
*/
public MyHashMap() {
this.values = new int;
}

/**
* Value will always be non-negative.
*/
public void put(int key, int value) {
this.values[key] = value + 1;
}

/**
* 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) {
return this.values[key] - 1;

}

/**
* Removes the mapping of the specified value key if this map contains a mapping for the key
*/
public void remove(int key) {
this.values[key] = 0;
}
}``````

So what did I do ?

I used a simple int array with predefined length of 1000001.

By default all values are 0 in Java. So we keep it the way it is and do not flash fill to -1 which can be another way.

While inserting the values we increment the value to plus 1 and while returning we decrease it to -1.

This helps us to tackle the boundary case that if key is not present, return -1.

Let's go through an example:

put(1, 5) -> this will insert 6 at index 1 as we are adding 1 to it while inserting.

So array becomes : values [0, 6, .... ]

get(1) -> this will return the value at index 1 and decrease 1 from it.

So we return values : 6 - 1 which is 5. This is equal to what we tried inserting earlier.

remove(1) -> this will make the value at location 1 to 0.

So array becomes : values [0, 0, .... ]

Now if we do a get(1) , it returns values : 0 - 1 which is -1.

Thus this satisfies the boundary condition.

Hope you liked this. Cheers!