LeetCode #706 Design HashMap 设计哈希映射

706 Design HashMap 设计哈希映射

Description:
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.

题目描述:
不使用任何内建的哈希表库设计一个哈希映射

具体地说,你的设计应该包含以下的功能

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

示例 :

MyHashMap hashMap = new MyHashMap();
hashMap.put(1, 1);          
hashMap.put(2, 2);         
hashMap.get(1);            // 返回 1
hashMap.get(3);            // 返回 -1 (未找到)
hashMap.put(2, 1);         // 更新已有的值
hashMap.get(2);            // 返回 1 
hashMap.remove(2);         // 删除键为2的数据
hashMap.get(2);            // 返回 -1 (未找到) 

注意:

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

思路:

哈希函数使用取余, 用拉链法解决冲突
Java代码参考源码实现
时间复杂度O(n), 空间复杂度O(1)

代码:
C++:

struct Node
{
    int nkey;
    int nval;
    Node* next;
    Node(int key, int val): nkey(key), nval(val), next(nullptr){}
};
const int len = 13;
class MyHashMap 
{
public:
    vector <Node*> arr;
    /** Initialize your data structure here. */
    MyHashMap() 
    {
        arr = vector<Node*> (len, new Node(-1, -1));
    }
    
    /** value will always be non-negative. */
    void put(int key, int value) 
    {
        Node* p = arr[key % len];
        Node* node;
        while (p) 
        {
            if (p -> nkey == key) 
            {
                p -> nval = value;
                return;
            }
            node = p;
            p = p -> next;
        }
        p = new Node(key,value);
        node -> next = p;
    }
    
    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    int get(int key) 
    {
        Node* node = arr[key % len];
        while (node) 
        {
            if (node -> nkey == key) return node -> nval;
            node = node -> next;
        }
        return -1;
    }
    
    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    void remove(int key) 
    {
        Node* node = arr[key % len];
        while (node) 
        {
            if (node -> nkey == key) node -> nval = -1;
            node = node -> next;
        }
    }
};

/**
 * 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);
 */

Java:

class MyHashMap {
    private static final int DEFAULT_CAPACITY = 16;
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private int size;
    private int capacity;
    private float factor; 
    private int threshold; 

    private Node[] table;

    @SuppressWarnings("unchecked")
    public MyHashMap(int capacity, float factor) {
        if (capacity <= 0) {
            capacity = DEFAULT_CAPACITY;
        }
        if (factor <= 0) {
            factor = DEFAULT_LOAD_FACTOR;
        }

        int minimumCapacity = 1;
        capacity -= 1;
        while (capacity != 0) {
            capacity >>= 1;
            minimumCapacity <<= 1;
        }
        capacity = minimumCapacity;

        this.factor = factor;
        this.capacity = capacity;
        this.threshold = (int) (capacity * factor);

        this.table = new Node[this.capacity];
    }

    public MyHashMap() {
        this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
    }

    private class Node {
        private int key;
        private int value;
        private Node next;

        Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }


    private int hash(Object key) {
        if (key == null) {
            return 0;
        }
        int hashCode = key.hashCode();
        return hashCode ^ (hashCode >>> 16);
    }

    public void put(int key, int value) {
        ensureCapacity();

        int pos = getPos(key, table);
        if (table[pos] == null) { 
            Node node = new Node(key, value);
            table[pos] = node;
            size++;
        } else {
            Node head = table[pos]; 
            Node tmp = head;
            while (tmp != null) {
                if (key == tmp.key) {
                    tmp.value = value; 
                    break;
                }
                tmp = tmp.next;
            }
            if (tmp == null) { 
                Node node = new Node(key, value); 
                node.next = head;
                table[pos] = node;
                size++;
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void ensureCapacity() {
        if (size >= threshold) { 

            capacity <<= 1;
            threshold = (int) (capacity * factor);

            Node[] newTable = new Node[capacity];
            for (Node node : table) {
                Node tmp = node; 
                while (tmp != null) { 
                    int pos = getPos(tmp.key, newTable); 

                    Node next = tmp.next;

                    tmp.next = newTable[pos];
                    newTable[pos] = tmp;

                    tmp = next;
                }
            }
            table = newTable;
        }
    }

    private int getPos(Object key, Node[] table) {
        return hash(key) & (table.length - 1);
    }

    public int get(int key) {
        int pos = getPos(key, table);
        if (table[pos] == null) { 
            return -1;
        } else { 
            Node head = table[pos]; 
            while (head != null) {
                if (key == head.key) {
                    return head.value;
                }
                head = head.next;
            }
            return -1;
        }
    }

    public void remove(int key) {
        int pos = getPos(key, table);

        if (table[pos] == null) { 
            return;
        } else {
            Node head = table[pos]; 
            Node preNode = null;
            while (head != null) {
                if (key == head.key) {
                    break;
                }
                preNode = head;
                head = head.next;
            }
            if (head != null) { 
                Node next = head.next;
                head.next = null;
                if (preNode == null) { 
                    table[pos] = next;
                } else {
                    preNode.next = next;
                }
                size--;
            }
        }
    }

    public int size() {
        return size;
    }

}

/**
 * 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);
 */

Python:

class Node:
    
    def __init__(self, key=None, val=None, next=None):
        self.key = key
        self.val = val
        self.next = next

class MyHashMap:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.size = 1000
        self.h = [Node() for _ in range(self.size)]

    def put(self, key: int, value: int) -> None:
        """
        value will always be non-negative.
        """
        p = self.h[key % self.size]
        c = p.next
        while c:
            if c.key == key:
                c.val = value
                break
            p = c
            c = c.next
        else:
            p.next = Node(key, value)

    def get(self, key: int) -> int:
        """
        Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key
        """
        c = self.h[key % self.size]
        while c:
            if c.key == key:
                return c.val
            c = c.next
        return -1

    def remove(self, key: int) -> None:
        """
        Removes the mapping of the specified value key if this map contains a mapping for the key
        """
        p = self.h[key % self.size]
        c = p.next
        while c:
            if c.key == key:
                p.next = c.next
                break
            p = c
            c = c.next


# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,406评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,976评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,302评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,366评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,372评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,457评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,872评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,521评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,717评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,523评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,590评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,299评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,859评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,883评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,127评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,760评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,290评论 2 342

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,440评论 0 13
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,714评论 0 38
  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,279评论 0 10
  • 1.什么是HashMap 基于哈希表的Map接口的非同步实现 此实现提供所有可选的映射操作,并允许使用null值和...
    苍賢阅读 510评论 0 1
  • 1.HashMap是一个数组+链表/红黑树的结构,数组的下标在HashMap中称为Bucket值,每个数组项对应的...
    谁在烽烟彼岸阅读 1,007评论 2 2