• LeetCode705. Design HashSet


    题目 

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

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

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

    考点

    1.哈希表O(1)。用数组空间换时间。data.resize(1000000,0);

    2.二维数组,优化空间复杂度,1000个空数组 ,对数字取1000的余作为哈希值,定位到二维数组中,再除1000得到二度的哈希值。


    思路

    solution1

    构造函数。顺序容器vector<int> data。重置数组大小:100w.

    增:key对应的val设为1。

    删:key对应的值设为0.

    判断是否存在:bool返回 data[key]==1.

    HashSet最有用的地方就是其能够在O(1)内判断某个元素是否存在,这都得归功于哈希表的作用。但是现在不让我们用了,但我们还是得保证其常数级的查找效率,那么就用空间来换时间吧。既然题目中说了数字的范围不会超过1000000,那么我们就申请这么大空间的数组,这样对于在HashSet中的数字,我们就将其标记为1,不在或者删除了的就标记为0,检测的时候就看其值是否为1即可.

    solution2.

    优化空间复杂度。二维数组,开始初始化1000个空数组,key%1000是哈希值(一维指针),key/1000是二维指针。

    优化空间复杂度,由于存入HashSet的数字也许不会跨度很大,那么直接就申请长度为1000000的数组可能会有些浪费,那么我们其实可以使用1000个长度为1000的数组来代替,那么就要用个二维数组啦,实际上开始我们只申请了1000个空数组,对于每个要处理的元素,我们首先对1000取余,得到的值就当作哈希值,对应我们申请的那1000个空数组的位置,在加入元素时,一旦计算出了哈希值,我们将对应的空数组resize为长度1000,然后根据哈希值key/1000来确定具体的加入位置。

    移除数字一样的,先计算出哈希值,如果对应的数组不为空的话,找到对应的位置并赋值为0。

    不过大家也可以看出来,我们在加入元素时会开辟1000的新空间,但是删除这个元素时,并没有检测这1000个位置是否均为0,是的话应该删除这1000个新空间。但是这样可能会使得删除函数变慢一些,


    代码

    solution1.

    class MyHashSet {
    public:
        /** Initialize your data structure here. */
        MyHashSet() {
            data.resize(1000000, 0);
        }
        
        void add(int key) {
            data[key] = 1;
        }
        
        void remove(int key) {
            data[key] = 0;
        }
        
        /** Returns true if this set contains the specified element */
        bool contains(int key) {
            return data[key] == 1;
        }
        
    private:
        vector<int> data;
    };

    solution2.

    优化空间复杂度,由于存入HashSet的数字也许不会跨度很大,那么直接就申请长度为1000000的数组可能会有些浪费,那么我们其实可以使用1000个长度为1000的数组来代替,那么就要用个二维数组啦,实际上开始我们只申请了1000个空数组,对于每个要处理的元素,我们首先对1000取余,得到的值就当作哈希值,对应我们申请的那1000个空数组的位置,在加入元素时,一旦计算出了哈希值,我们将对应的空数组resize为长度1000,然后根据哈希值key/1000来确定具体的加入位置。

    移除数字一样的,先计算出哈希值,如果对应的数组不为空的话,找到对应的位置并赋值为0。

    不过大家也可以看出来,我们在加入元素时会开辟1000的新空间,但是删除这个元素时,并没有检测这1000个位置是否均为0,是的话应该删除这1000个新空间。但是这样可能会使得删除函数变慢一些,

    class MyHashSet {
    public:
        /** Initialize your data structure here. */
        MyHashSet() {
            data.resize(1000,vector<int>());
            //二维数组初始化,第一个数是个数,第二个参数是元素类型,vector<int>()表示初始化为0的容器。要加()!!!!
        }
        
        void add(int key) {
            int hashkey=key%1000; 
            if(data[hashkey].empty()) 
            {
                data[hashkey].resize(1000,0); 
            }
             data[hashkey][key/1000]=1;
            //这个赋值操作写在if外部。只做一次哈希值判空!!
        }
        
        void remove(int key) {
            int hashkey=key%1000;  
            if(!data[hashkey].empty())
            {
                data[hashkey][key/1000]=0;
            }
        }
        
        /** Returns true if this set contains the specified element */
        bool contains(int key) {
            return !data[key%1000].empty()&& (data[key%1000][key/1000]==1);
        }
        
        private: vector<vector<int>> data;
    };
     
    /**
     * Your MyHashSet object will be instantiated and called as such:
     * MyHashSet obj = new MyHashSet();
     * obj.add(key);
     * obj.remove(key);
     * bool param_3 = obj.contains(key);
     */

    问题

  • 相关阅读:
    回望2010,展望2011
    Java加密解密
    纠正平时代码中一些简单的误区(附代码)(不断收集)
    Android模拟器代理上网
    ExifInterface 获取GPS数据
    用异或加密(Java版)
    解决Conversion to Dalvik format failed: Unable to execute dex: null
    Android如何快速卸载apk
    2010年的最后一天,我又辞工(日记)
    项目管理学习资料(经典)
  • 原文地址:https://www.cnblogs.com/lightmare/p/10416154.html
Copyright © 2020-2023  润新知