目录
一、查找表
考虑的基本数据结构,主要分为以下几种情况:
- 第一类: 查找有无--set
例如:元素'a'是否存在,通常用set:集合。set只存储键,而不需要对应其相应的值。set中的键不允许重复。
- 第二类: 查找对应关系(键值对应)--dict
元素'a'出现了几次:dict-->字典。dict中的键不允许重复。
- 第三类: 改变映射关系--map
通过将原有序列的关系映射统一表示为其他
1.1、算法应用
349. 两个数组的交集
-
题目描述
给定两个数组nums,求两个数组的公共元素。
如nums1 = [1,2,2,1],nums2 = [2,2]
结果为[2]
结果中每个元素只能出现一次
出现的顺序可以是任意的
- 解题思路
由于每个元素只出现一次,因此不需要关注每个元素出现的次数,用set的数据结构就可以了。记录元素的有和无。
把nums1记录为set,判断nums2的元素是否在set中,是的话,就放在一个公共的set中,最后公共的set就是我们要的结果。
- C++算法实现
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
set<int> set1(nums1.begin(),nums1.end());
set<int> set2(nums2.begin(),nums2.end());
vector<int> res;
for(auto i=set1.begin();i!=set1.end();++i){
if(set2.find(*i)!=set2.end()){
res.push_back(*i);
}
}
return res;
}
350. 两个数组的交集 II
- 题目描述
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
- 解题思路
元素出现的次数有用,那么对于存储次数就是有意义的,所以选择数据结构时,就应该选择dict的结构,通过字典的比较来判断;
记录每个元素的同时要记录这个元素的频次。
记录num1的字典,遍历nums2,比较nums1的字典的nums的key是否大于零,从而进行判断。
- C++算法实现
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> res;
map<int,int> temp;
for(int i=0;i<nums1.size();i++)
{
temp[nums1[i]]++;
}
for(int i=0;i<nums2.size();i++)
{
if(temp[nums2[i]]>0)
{
res.push_back(nums2[i]);
temp[nums2[i]]--;
}
}
return res;
}
242. 有效的字母异位词
- 题目描述
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
- 解题思路
判断异位词即判断变换位置后的字符串和原来是否相同,那么不仅需要存储元素,还需要记录元素的个数。可以选择dict的数据结构,将字符串s和t都用dict存储,而后直接比较两个dict是否相同。
- C++算法实现
bool isAnagram(string s, string t) {
if (s.size() != t.size())
{
return false;
}
int cNum[26] = {0};
for (int i = 0; i < s.size(); ++i)
{
cNum[s[i] - 'a']++;
}
for (int i = 0; i < t.size(); ++i)
{
if (cNum[t[i] - 'a'] == 0)
{
return false;
}
else
{
cNum[t[i] - 'a']--;
}
}
return true;
}
202. 快乐数
- 题目描述
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
- 解题思路
只需要判断有或无,不需要记录次数,故用set的数据结构。每次对求和的数进行append,当新一次求和的值存在于set中时,就return false.
- C++算法实现
bool isHappy(int n) {
set<int> sets;
while(n!=1){
int sum=0;
while(n>0){
sum+=pow((n%10),2);
n=n/10;
}
if(sets.find(sum)!=sets.end()){
return false;
}
sets.insert(sum);
n=sum;
}
return true;
}
290. 单词规律
- 题目描述
给出一个模式(pattern)以及一个字符串,判断这个字符串是否符合模式
示例1:
输入: pattern = "abba",
str = "dog cat cat dog"
输出: true
示例 2:
输入:pattern = "abba",
str = "dog cat cat fish"
输出: false
示例 3:
输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false
示例 4:
输入: pattern = "abba", str = "dog dog dog dog"
输出: false
- 解题思路
对应的相同index下的值,如dict1[index] = dict2[index],那么我们可以创建两个新的字典,遍历index对两个新的字典赋值,并比较value。
- C++算法实现
bool wordPattern(string pattern, string str) {
int n = pattern.size();
unordered_map<int, string> m;
vector<string> vec;//保存单词
string s;
for(const auto &c : str){
if(isspace(c)){
vec.push_back(s);
s.clear();
continue;
}
s += c;
}
vec.push_back(s);
if(n != vec.size()) return false;
for(int i = 0; i < n; ++i){
if(m.count(pattern[i])){
if(m[pattern[i]] != vec[i]) return false;
}else{
for(auto v : m){//此处可以优化,多一个哈希表set就可以免去查找
if(v.second == vec[i]) return false;
}
m[pattern[i]] = vec[i];
}
}
return true;
}
451. 根据字符出现频率排序
- 题目描述
给定两个字符串 s 和 t,判断它们是否是同构的。如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
输入: s = "egg", t = "add"
输出: true
示例 2:
输入: s = "foo", t = "bar"
输出: false
示例 3:
输入: s = "paper", t = "title"
输出: true
- 解题思路
思路与上题一致,可以考虑通过建两个dict,比较怎样不同,也可以将不同转化为相同。
- C++算法实现
string frequencySort(string s) {
map<char,int> m;
for(auto c:s){
if(m.count(c)){
m[c]++;
}else{
m[c]=1;
}
}
vector<pair<char,int>> vec(m.begin(),m.end());
sort(vec.begin(),vec.end(),[](const pair<char, int>& a, const pair<char, int>& b){return a.second>b.second;});
string res="";
for(auto it=vec.begin();it!=vec.end();++it){
while(it->second>0){
res+=it->first;
it->second--;
}
}
return res;
}