DAY06 哈希表

关于哈希表:

在要求快速查询,最小时间复杂度 O(1) 场景时候,需要想到哈希表。

(查的快,还需要对查询出的数据有排序需求时,要想到红黑树)

哈希表(感觉叫散列表更加直观):原始数据通过映射关系(哈希函数,一般是除留余数法),得到一个在表中离散的位置,映射过程中可能发生两个元素的位置相同的情况(哈希碰撞),降低哈希碰撞发生概率有两种设计:

1.让哈希表的长度等于素数;

2.哈希表已经占用的桶的个数/哈希桶的总个数>0.75(装载因子loadfactor)时,要扩容哈希表(扩容大小也为素数大小,例如从7扩容到23),扩容后所有的元素在哈希表中的位置都要重新确定,因此扩容的代价还是很大的。

哈希碰撞的解决办法有两种,线性探测法链地址法

 242. 有效的字母异位词 - 力扣(LeetCode)

数组就是简单的哈希表 ,当题目的数据有范围时(例如这道题,英文小写字母的类型是有限的,只有26种),要想到利用26个字母的ASCII码。

class Solution {
public:
    bool isAnagram(string s, string t) {
        vector<int>table(26,0);
        for(int i=0;i<s.size();i++){
            table[s[i]-'a']++;
        }
        for(int i=0;i<t.size();i++){
            table[t[i]-'a']--;
        }
        for(int i=0;i<26;i++){
            if(table[i]!=0){
                return false;
            }
        }
        return true;
    }
};

349. 两个数组的交集 - 力扣(LeetCode)

 这道题的描述是很经典的,输出要求去重无序,自然想到要使用unordered_set数据结构来做。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int>result_set;
        unordered_set<int>nums_set(nums1.begin(),nums1.end());
        //遍历nums2的元素,并将每次遍历的元素赋值给num
        for(int num:nums2){
            //如果找到了元素,它会返回一个指向该元素的迭代器;
            //如果没有找到,它会返回一个指向集合末尾的迭代器。
            if(nums_set.find(num)!=nums_set.end()){
                result_set.insert(num);
            }
        }
        //最后将set转成vector
        return vector<int>(result_set.begin(),result_set.end());
    }
};

如果对数组内元素的大小进行限制,也可以使用数组哈希表来解决

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int>result_set;
        int hash[1001]={0};
        for(int num : nums1){
            hash[num]=1;
        }
        for(int num :nums2){
            if(hash[num]==1){
                //利用unordered_set去重的特点
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(),result_set.end());
    }
};

202. 快乐数 - 力扣(LeetCode)

 需要注意对数值各位上单数操作的掌握。

class Solution {
public:
    int getNum(int n){
        int sum=0;
        while(n){
            sum+=(n%10)*(n%10);
            n/=10;
        }    
            return sum;
    }
    bool isHappy(int n) {
        unordered_set<int>result_set;
        while(1){
            int sum=getNum(n);
            if(sum==1){
                return true;
            }
            //如果找到了元素,它会返回一个指向该元素的迭代器;
            //如果没有找到,它会返回一个指向集合末尾的迭代器。
            else if(result_set.find(sum)!=result_set.end()){
                return false;
            }
            else {
                result_set.insert(sum);
            }
            n=sum;
        }
    }
};

1. 两数之和 - 力扣(LeetCode)

  • 为什么会想到用哈希表
  • 哈希表为什么用map
  • 本题map是用来存什么的
  • map中的key和value用来存什么的

         因为要遍历数组,查询符合题目要求的元素,所以想到用哈希表;元素大小不确定,返回值要求是元素的对应下标,所以不使用set(只有value),而选择使用map(value,key),这道题的map用来存放已经访问过的元素。key用来存放数组元素的值,value用来存放下标。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int ,int >hash;
        for(int i;i<nums.size();i++){
            auto iter=hash.find(target-nums[i]);
            //不等于末尾迭代器,说明找到了该元素
            if(iter!=hash.end()){
                return {iter->second,i};
            }
            //没找到,就把查询过的元素值和索引加到map中
            hash.insert(pair<int,int>(nums[i],i));
        }
        return {};
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值