LeetCode Notes_#706_设计哈希映射

LeetCode Notes_#706_设计哈希映射

Contents

题目

不使用任何内建的哈希表库设计一个哈希映射
具体地说,你的设计应该包含以下的功能

  • put(key, value):向哈希映射中插入(键,值)的数值对。如果键对应的值已经存在,更新这个值。
  • get(key):返回给定的键所对应的值,如果映射中不包含这个键,返回-1。
  • remove(key):如果映射中存在这个键,删除这个数值对。

注意:

  • 所有的值都在 [0, 1000000]的范围内。
  • 操作的总数目在[1, 10000]范围内。
  • 不要使用内建的哈希库。

思路分析

与设计HashSet一题是类似的,核心思路在于把要存储的数据利用哈希函数(散列函数)来分布到各个桶当中,然后再调用桶的增删查改方法,在桶里进行具体的操作。
HashSet的不同之处在于,我们这里不仅仅保存一个Key,还得保存一个Value,所以桶内部的数据类型需要自己定义一个Pair类型。
看起来函数很多,以为很复杂,技巧是先在纸上把所有函数,类列出来,设计好每个函数的功能,返回值等,然后再写代码,就不容易乱了。

解答

//Pair对象用来存储键值对
class Pair<U,V>{
    public U first;
    public V second;
    public Pair(U first, V second){
        this.first = first;
        this.second = second;
    }
}
//Bucket对象作为桶,存储Pair对象
class Bucket{
    List<Pair<Integer, Integer>> bucket;

    public Bucket(){
        bucket = new LinkedList<>();
    } 

    public void bucket_add(int key, int value){
        //ERROR:这里需要用一个flag做标识
        boolean found = false;
        //如果存在这个key,就更新它
        for(Pair<Integer,Integer> pair:bucket){
            if(pair.first == key){
                pair.second = value;
                found = true;
            }
        }
        //如果不存在这个key,直接插入新的键值对
        if(!found) bucket.add(new Pair<Integer,Integer>(key, value));
    }

    public int bucket_get(int key){
        for(Pair<Integer,Integer> pair:bucket){
            if(pair.first == key) return pair.second;
        }
        return -1;
    }

    public void bucket_remove(int key){
        for(Pair<Integer,Integer> pair:bucket){
            if(pair.first == key){
                //ERROR:找到对应的key之后需要break跳出循环
                bucket.remove(pair);
                break;
            }
        }
    }
}

class MyHashMap {
    int bucketNum = 769;
    Bucket[] bucketArray;

    /** Initialize your data structure here. */
    public MyHashMap() {
        bucketArray = new Bucket[bucketNum];
        for(int i = 0;i < bucketNum;i++){
            bucketArray[i] = new Bucket();
        }   
    }

    private int hash(int key){
        return key % bucketNum;
    }
    
    /** value will always be non-negative. */
    public void put(int key, int value) {
        int bucketIndex = hash(key);
        bucketArray[bucketIndex].bucket_add(key, value);
    }
    
    /** 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 bucketIndex = hash(key);
        return bucketArray[bucketIndex].bucket_get(key);
    }
    
    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    public void remove(int key) {
        int bucketIndex = hash(key);
        bucketArray[bucketIndex].bucket_remove(key);
    }
}

复杂度分析

时间复杂度:O(N/K),N是所有键值对的数量,K是桶的数量
空间复杂度:O(K+M),K是桶的数量,M是已经插入的键值对的数量

原文地址:https://www.cnblogs.com/Howfars/p/13708352.html