哈希表(一)

发布于:2024-10-13 ⋅ 阅读:(58) ⋅ 点赞:(0)

一、基础知识

哈希表的优点:

查找key的时间效率是O(1)

什么时候要用到哈希表:

查询元素的出现问题(是否出现过,是否在集合里,出现次数等)

哈希表的三种数据结构:

数组(数据范围较小时)

set(数据范围很大或者数据很散乱时)

map(需要同时用到key和value时)

二、数组

    bool isAnagram(string s, string t) {
    //仅26个英文字母,且是连续的,数据范围可为[0,25],用数组
    
    int hash[26]={0}; //初始化,记录字母出现次数的哈希数组
    if(s.size()!=t.size()){
        return 0;
    }
    for(int i=0;i<s.size();i++){ //遍历字符串,哈希计数
        hash[s[i]-'a']++; //映射,key值是字母-'a'(作差得起点),value是出现次数
        hash[t[i]-'a']--;
    }
    for(int i=0;i<26;i++){ //遍历哈希数组,看哈希计数是否为0(先+后-,若相等,最后为0)
        if(hash[i])
          return 0;
    }
    return 1;
    }

 对于26个连续的小写英文字母,要记录其出现的次数,用哈希数组即可;

遍历字符串,在hash[s[i]-'a']的位置进行++或--的操作;

最后判断哈希数组中是否全为0,若是则证明两个字符串是字母异位词。

三、set

vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        
     //unordered set自动去重,用来定义result
     unordered_set<int> result; //注意要写<int>
     //直接将数组1转变为set,便于判断数组2的元素是否在数组1集合中,减免了对1的for遍历
     unordered_set<int> nums1_set(nums1.begin(),nums1.end()); //转换是.begin(),.end()
     for(int i=0;i<nums2.size();i++){
        if(nums1_set.find(nums2[i])!=nums1_set.end()){
            //能找到,说明是交集元素
            result.insert(nums2[i]);
        }
     }
     return vector<int>(result.begin(),result.end()); //最终返回的是数组,转化为vector<int>
    }

对于装有零散数据(数据范围很大)的集合,用set

 将nums1数组变为集合1,遍历nums2数组,判断元素是否存在集合1中

若是,则加入result(unordered_set自动去重)中

四、map

vector<int> twoSum(vector<int>& nums, int target) {
        //用哈希map来存放遍历过的元素,数值作为key,索引作为value(哈希表查找key的效率是o(1),查找很快)

        //遍历数组元素,首先求该元素的配对元素,然后判断它是否在遍历过的map中,没有则将当前元素加入map,继续遍历下一个

        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++){
            int s=target-nums[i];
            auto iter=map.find(s); //查找key,找到时返回位置指针,找不到时返回.end()
            if(iter!=map.end()){
                //说明找到了,直接返回答案即可
                return {iter->second,i};//要写second,不能写value
            }
            map[nums[i]]=i;
        }
        return {};
    }

 对于既要用到数组元素值(key),又要用到索引(value)的情况,用map

(key是要查找的东西,所以将元素值作为key)

遍历数组元素,判断和当前元素对应的值(terget-nums[i])是否存在于遍历过的元素集合map中,

若是,则返回答案;若不是,则将当前元素加入map中,继续遍历下一元素