题目
不使用任何内建的哈希表库设计一个哈希映射(HashMap)。
实现 MyHashMap 类:
MyHashMap() 用空映射初始化对象
void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。
int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。
示例:
输入:
[“MyHashMap”, “put”, “put”, “get”, “get”, “put”, “get”, “remove”, “get”]
[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]]
输出:
[null, null, null, 1, -1, null, 1, null, -1]
解释:
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]
myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(1); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(3); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]
myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)
myHashMap.get(2); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]
myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]
myHashMap.get(2); // 返回 -1(未找到),myHashMap 现在为 [[1,1]]
提示:
0 <= key, value <= 10^6
最多调用 104 次 put、get 和 remove 方法
分析
这道题目要求自建一个map,最简单的办法就是通过数组实现,key作为数组的下标,value作为数组元素,这种有个问题在于需要给数组做一遍初始化为一个负数(因为map的value也可能是0),初始化一个10^6的数组还是需要一定的时间的,同时空间复杂度也很大,如果一直没有元素插入进来,就会有这个数组一直占着内存
或者换一个思路,减少空间复杂度的思路一定是链表,新增一个元素给他开一个空间,同时为了减少初始化的遍历时间,我们可以把这个数组的长度设置为1000,也无需任何初始化操作,这样后续肯定会有不同的key命中到相同的索引上,为了解决这个问题,我们把数组的元素类型设置成一个链表结点,链表结点的key是map的key,value是map的value,我们通过一个hash函数来把map的key换算到1000以内保证可以在数组中有对应的索引,这样如果我们的hash函数足够的分散的话,就能保证我们的链表也足够分散,put/get/remove函数的时间复杂度也不会太大。当然极端情况下所有的key都命中到一个链表,那这种情况下就需要遍历这个长链表去插入查询删除元素,这样其实也是非常耗时的
public class MyHashMap {Node[] a;public class Node{int key;int value;Node next;Node(int key,int value){this.key = key;this.value = value;this.next = null;}}public MyHashMap(){a = new Node[1000];}public void put(int key,int value) {int hashKey = getHash(key);Node head = a[hashKey];if(head == null) {a[hashKey] = new Node(key,value);} else {Node pre = null;while(head != null) {if(head.key ==key) {head.value = value;return;} else {pre = head;head = head.next;}}pre.next = new Node(key,value);}}public void remove(int key) {int hashKey = getHash(key);Node head = a[hashKey];if(head != null && head.key ==key) {a[hashKey] = head.next;return;}Node pre = null;while(head != null) {if(head.key == key) {pre.next = head.next;return;} else {pre = head;head = head.next;}}}public int get(int key) {int hashKey = getHash(key);Node head = a[hashKey];while(head != null) {if(head.key == key) {return head.value;} else {head = head.next;}}return -1;}public int getHash(int key) {int m = Integer.hashCode(key);return m / 1000;}
}
public class designHashMap {public static void main(String[] args) {MyHashMap myHashMap = new MyHashMap();myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]System.out.println(myHashMap.get(1)); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]System.out.println(myHashMap.get(3)); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)System.out.println(myHashMap.get(2)); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]System.out.println(myHashMap.get(2)); // 返回 -1(未找到),myHashMap 现在为 [[1,1]]}
}