Hash Table
适用条件:快速判断一个元素是否出现在集合中
解决数据结构:数组,set, map
优先使用unordered_set和 unordered_map,其底层逻辑为哈希表,查询和增删的时间都为O(1), 若需要有序,使用set和map,底层逻辑为红黑树,时间为O(logn),multiset和multimap的数值可重复,其他性质与set和map大致相同
Leetcode 242
采用数据结构:数组
class Solution {
public:
bool isAnagram(string s, string t) {
int record[26]{0};
for(auto i:s){
record[i-'a']++;
}
for(auto i:t){
record[i-'a']--;
}
for(int i=0; i<26; i++){
if(record[i] != 0)
return false;
}
return true;
}
};
如果两个为异位词,那么字母出现的数量一定是一样的,所以设置一个数组判断两个字符串字母出现的数量,如果一致,则为异位词
Leetcode 349 Intersection of Two Arrays
一.使用set
一些set的基础知识:
set初始化
unordered_set<int> set; //空集
unordered_set<int> set(set1); //复制set1
unordered_set<int> set(num.begin(), num.end());
(arr, arr+5);
常用函数
set.empty(); // 判断是否为空
set.find(num);//查找num是否在集合中,若不是返回end()
set.count(num); // 查找出现的次数
set.insert(num);
传入一个参数
set.insert("num");//会返回迭代器和一个布尔值说明插入是否成功。如果元素被插入,返回的迭代器会指向新元素;如果没有被插入,迭代器指向阻止插入的元
可以传入两个参数
set.insert(pr.first, "num");//第一个为迭代器的位置,第二个为插入值,此时会返回一个迭代器
set.erase();
set.clear();
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> res;
unordered_set<int> num_set(nums1.begin(), nums1.end());
for(int num:nums2){
if(num_set.find(num) != num_set.end()){
res.insert(num);
}
}
return vector<int>(res.begin(), res.end());
}
};
题中需要注意的点:
find失败返回的值是end()
最后的返回值是vector
tips:
什么时候使用set?
(这道题只跟数组对比)数组需要确定容器的大小,如果题目中没有给出数组大小的范围,则必须使用set(这道题给了范围,所以也可以使用数组);需要存储的数据比较分散,这样会占用过大的空间但闲余部分较多
为什么使用unordered_set?
因为这道题不需要有序,且不需要重复
二.使用array
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
int hash[1000] {0};
unordered_set<int> res;
for(int num:nums1){
hash[num] ++;
}
for(int num:nums2){
if(hash[num] != 0){
res.insert(num);
}
}
return vector<int> (res.begin(),res.end());
}
};
Leetcode 202 Happy Number
class Solution {
public:
int getSum(int n){
int sum = 0;
while(n >= 1){
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;
}
}
};
当出现重复的sum值的时候,就代表会无限循环
所以这道题的目标就是就是找到有没有重复的sum值
Leetcode 1 Two sum
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for(int i =0; i<nums.size(); i++){
if(map.find(target-nums[i]) != map.end()){
return vector<int> {i,map.at(target-nums[i])};
}else{
map.insert(make_pair(nums[i], i));
}
}
return {};
}
};
map?
既需要存储一个数组的所有值,也需要存储每个值所在的位置
注意:
map insert的时候需要写pair<int, int>
iter->second 指的是返回这个迭代器中的第二个值,在map中我们存储为(key, val),所以这里返回的是val,即数组每个元素所在的位置
auto iter = map.find(target - nums[i]);
if(iter != map.end()) {
return {iter->second, i};
}