zoukankan      html  css  js  c++  java
  • 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是已经插入的键值对的数量

  • 相关阅读:
    json数据在前端(javascript)和后端(php)转换
    几个提高效率的PHOTOSHOP秘密快捷键
    移动端ios针对input虚拟键盘挡住的问题
    前端适配移动端的方法
    完美兼容IE10以下所有版本
    vscode vue文件格式化没效果
    官网顶部的标题左移动
    模拟后台一次性返回所有数据
    关于上传图片的问题
    iframe标签在PC端的使用
  • 原文地址:https://www.cnblogs.com/Howfars/p/13708352.html
Copyright © 2011-2022 走看看