超全哈希表

哈希表的适用场景与使用方法

哈希表适用场景:

哈希表适用场景:用于快速判断一个元素是否出现在集合里。

常见方法:

常见三的种哈希结构:数组、集合(set)、映射(map)

数组:

数组是最简单的哈希表,但因数组大小有限,不适用于值少、跨度大且分散的情况。

有效的字母异位词

在这里插入图片描述

#include <iostream>
#include <string.h>
using namespace std;

int main() {
	string s, t;
	cin >> s >> t;
	int recode[26] = {0}; //题目可知只包含小写字母,固大小设置为26
	for (int i = 0; i < s.size(); i++) {
		recode[s[i] - 'a']++; //将各字母按顺放入recode,并记录次数
	}
	for (int j = 0; j < t.size(); j++) {
		recode[s[j] - 'a']--; //每找一次,减一
	}
	for (int i = 0; i < 26; i++) {
		if (recode[s[i]] != 0)
			return 0;
	}

	return 1;
}

赎金信

在这里插入图片描述

分析:
“只包含小写字母”!!!!
固用长度为26的数组来解决该问题最为合适
①以字母为下表,以值来记录次数
②若找到目标值则次数减一,若次数小于0则返回false

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        if(ransomNote.size()>magazine.size()) return false;
        int record[26]={0};
        for(int i=0;i<magazine.size();i++) record[magazine[i]-'a']++;
        for(int j=0;j<ransomNote.size();j++){
            if(record[ransomNote[j]-'a']!=0) record[ransomNote[j]-'a']--;
            else return false;
        }
        return true; 
    }
};

集合(set)

主要使用set,来解决值少、跨度大且分散的情况。

C++中共有三种可用set:
std::set
std::multiset
std::unordered_set
std::set与std::multiset的底层实现是红黑树,std::unordered_set的底层实现是哈希表,固选用std::unordered_set的效率最高。
std::unordered_set适用于以下场景:

  • 快速查找 (即哈希)
  • 无序
  • 去重
两个数组的交集

在这里插入图片描述

#include <iostream>
#include <string.h>
#include <unordered_set>
#include <vector>
using namespace std;

int main() {
	vector<int> nums1;
	vector<int> nums2;
	unordered_set<int> result;
	unordered_set<int> num1(nums1.begin(), nums1.end());
//	将nums1中的值传入set(为实现快速查找与去重)
	for (int num : nums2) {
		if (num1.find(num) != num1.end())
			result.insert(num);
		//若在nums2的值在num1中被找到,就插入结果中
	}
	//结果返回result,因为是自己编译器写的所以只能返回1了
	//return vector<int>(result.begin(),result.end());
	return 1;
}

快乐数

在这里插入图片描述

分析:
题中提到无限循环,固只用判断一个数是否为重复出现(哈希的快速查找),若否则继续循环,若是则跳出循环。

class Solution {
public:
    int getsum(int n){
            int sum=0;
            while(n){
                sum+=(n%10)*(n%10);
                n/=10;
            }
            return sum;
        }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1){
            int sum=getsum(n);
            if(sum==1) return true;
            if(set.find(sum)!=set.end()) return false;
            else set.insert(sum);
            n=sum;
        }
        
    }
};

映射(map)

两数之和

在这里插入图片描述

分析:
该题需要:①遍历元素找到目标值②记录下标并返回
固此种情形用map较为合适,map:map[key]=values (有些像Python中的字典)
用key来存放元素,values存放下标

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++){
            auto it=map.find(target-nums[i]);//it此时为:it[key]=values
            if(it!=map.end()) return {it->second,i};//it->first=key,it->second=values
            else map.insert(pair<int,int>(nums[i],i));//若未找到则将该值和其下标插入map,用于后续查找 
        }
        return{};
    }
};
四数相加

在这里插入图片描述

该题为哈希经典题目
分析:
可将该题分为2数之和,固需将nums1和nums2的和为第一个数x,将nums3和nums4的和为第二个数y。
①以x为key,以其出现的次数为values
②在map中找(0-(x)),若找到则result+=map[0-(x)]

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
        unordered_map<int,int> map;
        for(int a:nums1){
            for(int b:nums2)
            map[a+b]++;//以num1和num2的和为key,以和的次数为values
        }
        int count=0;
        for(int c:nums3){
            for(int d:nums4)
            if(map.find(0-(c+d))!=map.end()) count+=map[0-(c+d)];
        }
        return count;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值