【刷题3】找到字符串中所有字母异位词、串联所有单词的子串

一、找到字符串中所有字母异位词

题目:
在这里插入图片描述

思路:
用一个变量count来统计有效字符的个数。哈希表2统计字符串p的每个字符出现的个数,然后遍历字符串s,先进窗口,相同的映射位置,哈希表1该位置的个数<=哈希表2的个数,count++(比目标数小才要++,超过了就不需要++,有等号是因为先进窗口)。滑动窗口是固定大小的,所以right-left+1不能大于字符串p的长度。如果超过固定长度,先判断哈希表的位置,哈希表1该位置的个数<=哈希表2的个数,count- -(比目标数大去掉也无效,小于了有效数就减少,等于是因为先判断的,后面要哈希表位置要减减),然后出窗口。判断count等于字符串p的长度,更新结果(大于等于怎么办?不会出现)。

代码:

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;
        int hash1[26] = { 0 };
        int hash2[26] = { 0 };
        for (auto e : p) hash2[e - 'a']++;
        int left = 0, right = 0, count = 0;
        while (right < s.size())
        {
            hash1[s[right] - 'a']++;//先进窗口,再判断
            if (hash1[s[right] - 'a'] <= hash2[s[right] - 'a']) count++;
            while (right - left + 1 > p.size())
            {
                if (hash1[s[left] - 'a'] <= hash2[s[left] - 'a']) count--;//先判断
                hash1[s[left] - 'a']--;//再出窗口
                ++left;
            }
            if (count == p.size()) ret.push_back(left);
            ++right;
        }
        return ret;
    }
};

二、串联所有单词的子串

题目:
在这里插入图片描述

思路:滑动窗口+哈希表
整体思路与上一道题相同,但是有些区别。

容器使用:unordered_map<string, int>
循环次数:是单词的个数(每个单词的个数是相同的)
定义窗口的指针(下标)left、right每次从 i 开始(多次循环的缘故)
固定窗口大小:words的长度 * 单词长度
截取字符串:substr(从哪开始,截取几个)
移动步长:单词的长度

细节:第一个unordered_map用来统计不同单词的个数,第二个unordered_map要放在循环里面,因为每次算进去的单词可能会变化
在这里插入图片描述
整体思路:进窗口、判断、出窗口、更新结果

代码:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ret;
        unordered_map<string, int> hash1;//容器
        for (auto e : words) hash1[e]++;//先放入,便于判断
        for (int i = 0; i < words[0].size(); i++)//单词个数的循环次
        {
            //循环里的容器,注意!每次循环该容器的内容不一样了!
            //所以是临时的(每次循环)
            unordered_map<string, int> hash2;
            int left = i, right = i, count = 0;//注意从i开始
            while (right < s.size())//遍历字符串s
            {
                string str1 = s.substr(right, words[0].size());//截取字符串
                hash2[str1]++;//先进窗口
                if (hash2[str1] <= hash1[str1]) count++;//再判断
                while (right - left + 1 > words.size() * words[0].size())//固定窗口大小
                {
                    string str2 = s.substr(left, words[0].size());//截取字符串
                    if (hash2[str2] <= hash1[str2]) count--;//先判断
                    hash2[str2]--;//再出窗口
                    left += words[0].size();//移动步长
                }
                if (count == words.size()) ret.push_back(left);//更新结果
                right += words[0].size();//移动步长
            }
        }
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值