查找表相关问题总结
一、查找表分类
查找问题一般分为两类查找问题
- 查找有无 使用set,里面没有重复的键,唯一,即只有键,没有键值
- 查找对应关系(键值对应) 使用map
c++语言中,map与set底层实现为平衡二叉树;而unorder_set与unorder_map底层实现为哈希表,因此也就失去了数据的顺序性。
###二、常见的操作
- insert
- find
- erase
- change(一般多用在map这种数据结构中)
需要注意的是在各个程序语言特性中其实现机制不一样
/**
* 349.求两个数组的交集
* 每个元素是唯一的
* */
class Solution1 {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int>myset(nums1.begin(),nums1.end());
//vector<int> result;
set<int>resultset;
for(int i = 0; i < nums2.size(); i++){
if(myset.find(nums2[i]) != myset.end())
resultset.insert(nums2[i]);
}
return vector<int>(resultset.begin(),resultset.end());
}
};
/**此题是不是有问题
* 350.两个数组的交集
* 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致!!!!!此处是不是有错误
* 我们可以不考虑输出结果的顺序
* 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]输出: [4,9]
* */
class Solution2 {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
map<int,int>mymap;
vector<int>result;
for(auto c:nums1)
mymap[c]++;
for(int i = 0; i< nums2.size(); i++){
if(mymap[nums2[i]]>0 ) {
result.push_back(nums2[i]);
mymap[nums2[i]]--;
}
}
return result;
}
};
/**
* 242.有效的字母异位词
*
* */
class Solution3 {
public:
// bool isAnagram(string s, string t) {
// if(s.size() != t.size())
// return false;
// if(s.empty())//忘记了空集
// return true;
//
// unordered_map<char ,int >mymap;
// unordered_map<char ,int >mymap2;
// for(auto c : s)
// mymap[c]++;
// for(auto c : t)
// mymap2[c]++;
// unordered_map<char,int>::iterator iter;
// int count = 0;
// for(iter = mymap.begin();iter != mymap.end(); iter++)
// if(mymap2[iter->first] == iter ->second)
// count++;
// if(count == mymap.size())//之前此处代码逻辑出错了
// return true;
// else
// return false;
// }
//此处代码进行了优化
bool isAnagram(string s, string t) {
if(s.size() != t.size())
return false;
if(s.empty())//忘记了空集
return true;
unordered_map<char ,int >mymap;
unordered_map<char ,int >mymap2;
for(int i = 0; i < s.size(); i++)
{
mymap[s[i]]++;
mymap2[t[i]]++;
}
unordered_map<char,int>::iterator iter;
int count = 0;
for(iter = mymap.begin();iter != mymap.end(); iter++)
if(mymap2[iter->first] != iter ->second)
return false;//只要不满足就返回false
return true;
}
};
/**
* 202.快乐数
* */
class Solution4 {
public:
bool isHappy(int n) {
assert(n > 0);
int temp = n;
set<int> myset;
while (n != 1) {
int sum = 0;
while (n > 0) {
sum += (n % 10) * (n % 10);
n /= 10;}
if (myset.find(sum) == myset.end())//如果没有找到,则将其进行插入
myset.insert(sum);
else {//如果找到了,说明存在循环,则不是幸福数
return false;
}
n = sum;
}
return true;
}
};
/**
* 290 单词模式
* 利用两个哈希表的键值对应来做
* */
class Solution5 {
public:
bool wordPattern(string pattern, string str) {
// map<string,int>mymap1;
// map<char,int>mymap2;
unordered_map<string, char> mymap1;
unordered_map<char, string> mymap2;
vector<string> strVector;
str.push_back(' ');//补个空格便于分割
int index = 0;
for (int i = 0; i < str.size(); ++i) {
if (str[i] != ' ')
index++;
else {
strVector.push_back(str.substr(i - index, index));
index = 0;
}
}
if (pattern.size() != strVector.size())
return false;
for (int i = 0; i < pattern.size(); i++) {
if (mymap2.find(pattern[i]) == mymap2.end() && mymap1.find(strVector[i]) == mymap1.end()) {
mymap2[pattern[i]] = strVector[i];
mymap1[strVector[i]] = pattern[i];
} else if (mymap1[strVector[i]] != pattern[i]) {//如果键值不等或者该键值不存在(此时也不等于)
return false;
}
}
return true;
}
};
/**
* 205. 同构字符串
* */
class Solution6 {
public:
bool isIsomorphic(string s, string t) {
unordered_map<char, char> mymap1;//此处换成哈希表非常的快
unordered_map<char, char> mymap2;
if (s.size() != t.size())
return false;
for (int i = 0; i < s.size(); i++) {
if (mymap2.find(s[i]) == mymap2.end() && mymap1.find(t[i]) == mymap1.end()) {
mymap2[s[i]] = t[i];
mymap1[t[i]] = s[i];
} else if (mymap1[t[i]] != s[i]) {//如果键值不等或者该键值不存在(此时也不等于)
return false;
}
}
return true;
}
};
/*相关的解决思路,速度非常快, string可以直接查找
class Solution {
public:
bool isIsomorphic(string s, string t) {
if(s.length()==0)return true;
int i=0;
while(i<s.length())
{
if(s.find(s[i])!=t.find(t[i]))
return false;
i++;
}
return true;
}
};*/
/**
* 451.根据字符出现频率排序
* 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
* */
//自己写的写错了
class Solution {
public:
string frequencySort(string s) {
unordered_map<char, int> mymap1;
map<int, char> mymap2;
for( auto c : s){
mymap1[c]++;
}
unordered_map<char ,int>::iterator iter;
for( iter = mymap1.begin(); iter != mymap1.end(); iter++){
mymap2[iter->second] = iter -> first;
}
string result;
map<int ,char>::iterator iter2;
for( iter2 = mymap2.begin(); iter2 != mymap2.end(); iter2++){
for( int i = 0; i < iter ->first; i ++ )
result.push_back(iter->second);
}
return result;
}
};
/*利用了pair
* string frequencySort(string s) {
string res = "";
unordered_map<char, int> myMap;
vector<pair<char, int>> myVec;
//统计所有的字母出现的频次
for (int i = 0; i < s.size(); i++) {
myMap[s[i]]++;
}
//将字母及频次存入Vector,便于之后的排序
for (auto it = myMap.begin(); it != myMap.end(); it++) {
myVec.push_back(make_pair(it->first, it->second));
}
//按照字母出现的频次从大到小进行排序
sort(myVec.begin(), myVec.end(), [](const pair<char, int>& x, const pair<char, int>& y) -> int {
return x.second > y.second;//labmda表达式
});
//将排序后的字母,根据其频次,依次添加对应数量的该字母进入结果字符串中
for (auto it = myVec.begin(); it != myVec.end(); it++) {
for (int i = 0; i < it->second; i++) {
res += it->first;
}
}
return res;
}
* */
还有一个典型的查找表问题,就是leetcode当中的k-sum 问题