22. 有效字母异位词、384. 赎金信、49. 字母异位词分组、438. 找到字符串中所有字符异位词

22. 有效字母异位词

题目描述:给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

解答:

        题目中涉及到统计字母是否出现,字母的出现次数,第一反应便是使用哈希表。本题思路比较简单,使用两个哈希表分别存储字符串s,t中的字母出现次数,再比对两个哈希表即可。

        此外本题中hash表的键值无重复元素(26个字母),并且不会涉及到修改键值,故此处采用了map。此题使用数组来实现哈希表也十分方便。

代码实现:

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size() != t.size())
            return false;
        map<char, int>hash_mapS, hash_mapT;
        for (auto c:s)//遍历字符串,将其存入哈希表中
            hash_mapS[c] = hash_mapS.find(c) != hash_mapS.end() ? hash_mapS[c]+1 : 1;
        for (auto c:t)
            hash_mapT[c] = hash_mapT.find(c) != hash_mapT.end() ? hash_mapT[c]+1 : 1;
        for (auto m:s){//两个哈希表进行比对
            if (hash_mapS[m] != hash_mapT[m])
                return false;
        }
        return true;
    }
};

384. 赎金信

题目描述:

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

解答:

        本题涉及到字符串比对,采用哈希表解决。第一步,遍历magazine字符串并存入相应的哈希表hash_Mag中。第二步,遍历ransomNote,同时hash_Mag进行查找,若找到且值大于0则减一继续寻找;否则返回false。遍历结束后返回 true。

代码实现:

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        map<char, int>hash_Mag;
        for (auto c:magazine)
            hash_Mag[c] = hash_Mag.find(c) != hash_Mag.end() ? hash_Mag[c]+1 : 1;
        for (auto t:ransomNote){
            if (hash_Mag.find(t) != hash_Mag.end()){
                if (hash_Mag[t] > 0)
                    hash_Mag[t]--;
                else
                    return false;
            }
            else
                return false;
        }
        return true;
    }
};

49. 字母异位词分组

题目描述:

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

解答:

法一:采用暴力法。先进行排序,排序后使用两个循环依次进行比较,找到相同的归为一组,循环结束后即分组完成。

在实现时有个坑,对于string类型的在添加到vector时应该使用vec.push_back()。

代码实现:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<string> order;//记录排序后的字符串数组
        for (int i = 0; i<strs.size(); i++){//对strs中的字符串进行排序,放置到另一个空间中
            string str = strs[i];
            sort(str.begin(), str.end());
            order.push_back(str);
        }
        vector<vector<string>> ans;
        for(int i = 0; i<strs.size(); i++){//遍历新的字符串数组order,对于相同的归为一类
            vector<string> group;
            if(order[i] != "0"){
               group.push_back(strs[i]);
                for (int j = i+1; j<strs.size(); j++){
                    if (order[i] == order[j]){
                        group.push_back(strs[j]);
                        order[j] = "0";//归类后置空
                    }        
                }
                ans.push_back(group);
            }
        }
        return ans;
    }
};

法二:因为涉及到字符串的比对,考虑使用哈希表 (键值为string类型,值为vector<string>类型,用于存储同类的一组string值)。

        (1) 对字符串进行排序,将排序后的字符串作为哈希表的键值,同时将排序前的值插入到哈希表中。

        (2) 然后再对哈希表进行遍历,存储值(hash.second)到二维向量中即可。

代码实现:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> hash;
        for(auto str : strs) {
            string s = str;
            sort(s.begin(), s.end());//对字符串排序,作为哈希表的键值
            hash[s].push_back(str);//存储原值到哈希表中,且同类的分到了一组中
        }
        vector<vector<string>> ans;
        for(auto h : hash) {
            ans.push_back(h.second);
        }
        return ans;
    }
};

438. 找到字符串中所有字符异位词

题目描述:

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

解答:很容易想到采用暴力法进行解决,将t串用哈希表存储起来,s串每次移动一个位置,逐个进行比较。但是这样复杂度过高,从[i, j] 到[i+1, j+1]包含了已经检查过的信息[i+1, j],多次重复检查没有必要

        可以先将s串中的第一段[i, j]用哈希表存储起来,与t串比较后仅在哈希表中删除s[i]增加s[i+1]即可(前后一起动)。

        对于两个哈希表的比较问题,如果采用排序后比较复杂度过高,可直接用vector数组构成哈希表,用“==”比较即可

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        int lenP = p.length();
        int lenS = s.length();
        vector<int>result;//存储结果
        vector<int>subS(26, 0);//采用vector存储,易于比较
        vector<int>subP(26, 0);
        if (lenS < lenP)
            return result;
        for (auto ch:p)//将p串存入哈希表中
            subP[ch - 'a']++;
        int low = 0;
        for (int fast = 0; fast<lenS; fast++){
            subS[s[fast] - 'a']++;
            if (fast >= lenP-1){//长度等于p串时每次前后指针一起移动
                if (subS == subP)
                    result.push_back(low);
                subS[s[low] - 'a']--;
                low++;
            }
        }
        return result;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值