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

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

分析:本题采用哈希表+滑动窗口的方法来实现。

  • 首先定义一个哈希表用来存储要匹配的子串(p)的字符和字符出现频率,即key为不同的字符,value为字符出现的次数;
  • 再定义一个哈希表来存储在s字符串上进行滑动的窗口中字符的频率;
  • 再用一个整数来记录两个哈希表中频率相同的字符串的个数;
  • 滑动窗口的大小为right-left ,通过更新right和left来控制滑动窗口的大小

解题步骤:

  1. 定义左右指针和字符数量,遍历字符串p,将字符及其出现次数存储到哈希表pMap中;

    int left = 0, right = 0, count = 0;
    for (char n : p) {
        pMap[n]++;
    }
    
  2. 遍历字符串s, 更新右边界,如果pMap中存在s[right],更新sMap中的s[right]的次数,如果sMap[s[right]] == pMap[s[right]],说明sMap中存在和pMap中字符频率相同的字符,count加1, 更新右边界;

    if (pMap.count(s[right])) {
        sMap[s[right]]++;
        if (sMap[s[right]] == pMap[s[right]]) {
            count++;
        }
    }
    right++;
    
  3. count == pMap.size(), 即当前滑动窗口内包含了字符串p中所有的字符,且每种字符的频率都与字符串p中对应,并且如果right - left == pLen ,即滑动窗口的大小也等于字符串p的大小,就可以将左边界添加到答案数组中了,这里为什么还要再判断right - left == pLen是因为,但sMap中存在所有pMap中的字符且频率对应的时候,还可能存在pMap中不存在的字符,所以只有当right - left == pLen才是匹配的字符串,例如在示例1中,当left = 1,right =9时,sMap 包含pMap 中的字符及其出现频率,但是此时并不是匹配的子串;

  4. 添加结果以后,判断当pMap 中是否存在s[left]时,若存在要对sMaps[left]的频率减1,因为滑动窗口的左边界将被更新,不再包含此时的left,如果sMap[s[left]] < pMap[s[left]],则count也要减1,表示此时当前窗口不再和字符串p匹配,最后向右移动left指针;

    while (count == pMap.size()) {
        if (right - left == pLen) {
            res.push_back(left);
        }
        if (pMap.count(s[left])) {
            sMap[s[left]]--;
            if (sMap[s[left]] < pMap[s[left]]) {
                count--;
            }
        }
        left++;
    }
    
  5. 最后返回结果res.

完整代码

vector<int> findAnagrams(string s, string p) {
    unordered_map<char, int> pMap, sMap;
    int sLen = s.size();
    int pLen = p.size();
    if (sLen < pLen) return {};
    int left = 0, right = 0, count = 0;
    vector<int> res;
    for (char n : p) {
        pMap[n]++;
    }
    while (right < sLen) {
        if (pMap.count(s[right])) {
            sMap[s[right]]++;
            if (sMap[s[right]] == pMap[s[right]]) {
                count++;
            }
        }
        right++;
        while (count == pMap.size()) {
            if (right - left == pLen) {
                res.push_back(left);
            }
            if (pMap.count(s[left])) {
                sMap[s[left]]--;
                if (sMap[s[left]] < pMap[s[left]]) {
                    count--;
                }
            }
            left++;
        }
    }
    return res;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值