LeetCode(705 & 706):设计哈希集合 & 设计哈希映射 Design HashSet & HashMap(Java)

2019.11.10 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

github:https://github.com/ChopinXBP/LeetCode-Babel

数据结构题,应知应会。

HashSet可以用二维数组进行动态开辟空间,避免直接开辟过大的一维数组造成资源浪费。

HashMap容量初始为16,需要考虑负载,一旦数量-容量比大于负载系数(0.75),进行再散列,将容量扩大为原来的两倍(保持2的幂次)。

在2的幂次的容量的情况下,哈希值计算有:

key & (length - 1) == key % length

补充:
java中HashSet底层其实是HashMap,HashSet的add方法底层调用HashMap的put方法,添加的value是一个固定的Object对象常量PRESENT。

private transient HashMap<E,Object> map;

// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

public HashSet() {
    map = new HashMap<>();
}

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

传送门:设计哈希集合

Design a HashSet without using any built-in hash table libraries.

To be specific, your design should include these functions:

add(value): Insert a value into the HashSet.

扫描二维码关注公众号,回复: 8567457 查看本文章

contains(value) : Return whether the value exists in the HashSet or not.

remove(value): Remove a value in the HashSet. If the value does not exist in the HashSet, do nothing.

不使用任何内建的哈希表库设计一个哈希集合

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

add(value):向哈希集合中插入一个值。

contains(value) :返回哈希集合中是否存在这个值。

remove(value):将给定值从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。

示例:
MyHashSet hashSet = new MyHashSet();
hashSet.add(1);         
hashSet.add(2);         
hashSet.contains(1);    // 返回 true
hashSet.contains(3);    // 返回 false (未找到)
hashSet.add(2);          
hashSet.contains(2);    // 返回 true
hashSet.remove(2);          
hashSet.contains(2);    // 返回  false (已经被删除)

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


/**
 *
 * Design a HashSet without using any built-in hash table libraries.
 * 不使用任何内建的哈希表库设计一个哈希集合
 *
 */

public class DesignHashSet {
    class MyHashSet {

        private int buckets = 1000;
        private int itemsPerBucket = 1001;
        private boolean[][] table;

        /** Initialize your data structure here. */
        public MyHashSet() {
            table = new boolean[buckets][];
        }

        //计算哈希值(商对应桶组)
        public int hash(int key){
            return key / buckets;
        }

        //计算位置(余数对应桶号)
        public int pos(int key){
            return key % buckets;
        }

        public void add(int key) {
            int hashkey = hash(key);
            if(table[hashkey] == null){
                table[hashkey] = new boolean[itemsPerBucket];
            }
            table[hashkey][pos(key)] = true;
        }

        public void remove(int key) {
            int hashkey = hash(key);
            if(table[hashkey] != null){
                table[hashkey][pos(key)] = false;
            }
        }

        /** Returns true if this set contains the specified element */
        public boolean contains(int key) {
            int hashkey = hash(key);
            return table[hashkey] != null && table[hashkey][pos(key)];
        }
    }

/**
 * Your MyHashSet object will be instantiated and called as such:
 * MyHashSet obj = new MyHashSet();
 * obj.add(key);
 * obj.remove(key);
 * boolean param_3 = obj.contains(key);
 */
}




传送门:设计哈希映射

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.

不使用任何内建的哈希表库设计一个哈希映射

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

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]范围内。
不要使用内建的哈希库。


/**
 *
 * Design a HashMap without using any built-in hash table libraries.
 * 不使用任何内建的哈希表库设计一个哈希映射
 *
 */

public class DesignHashMap {

    class MyHashMap {

        private class Node{
            int key;
            int value;
            Node next;
            public Node(int k, int v, Node n){
                key = k;
                value = v;
                next = n;
            }
        }

        private final double LOAD_FACTOR = 0.75;
        private Node[] nodes;
        private int size;

        /** Initialize your data structure here. */
        public MyHashMap() {
            nodes = new Node[16];
            size = 0;
        }

        //计算哈希值(当length为2的幂次时,key & (length - 1) == key % length)
        private int hash(int key){
            return key & (nodes.length - 1);
        }

        //每次再散列成原数组的两倍
        private void rehash(){
            Node[] temp = nodes;
            nodes = new Node[temp.length << 1];
            size = 0;
            for(Node head : temp){
                for(Node p = head; p != null; p = p.next){
                    put(p.key, p.value);
                }
            }
        }

        /** value will always be non-negative. */
        public void put(int key, int value) {
            int hashkey = hash(key);
            //先遍历链表里是否已经存在相同key值,若存在则覆盖value
            for(Node p = nodes[hashkey]; p != null; p = p.next){
                if(p.key == key){
                    p.value = value;
                    return;
                }
            }
            //若链表中不存在则将结点加在开头
            nodes[hashkey] = new Node(key, value, nodes[hashkey]);
            size++;
            //若当前size比例超过负债系数,则进行再散列
            if((double)size / nodes.length > LOAD_FACTOR){
                rehash();
            }
        }

        /** 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 hashkey = hash(key);
            for(Node p = nodes[hashkey]; p != null; p = p.next){
                if(p.key == key){
                    return p.value;
                }
            }
            return -1;
        }

        /** Removes the mapping of the specified value key if this map contains a mapping for the key */
        public void remove(int key) {
            int hashkey = hash(key);
            Node newhead = new Node(-1, -1, nodes[hashkey]);
            for(Node p = newhead; p.next != null; p = p.next){
                if(p.next.key == key){
                    p.next = p.next.next;
                    size--;
                    break;
                }
            }
            nodes[hashkey] = newhead.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);
 */
}




#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

发布了246 篇原创文章 · 获赞 316 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/102997158