【算法系列(三)】:查找

目录

 

一、查找表

1.1、算法应用

349. 两个数组的交集

350. 两个数组的交集 II

242. 有效的字母异位词

202. 快乐数

290. 单词规律

451. 根据字符出现频率排序


一、查找表

考虑的基本数据结构,主要分为以下几种情况:

  • 第一类: 查找有无--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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值