【算法】滑动窗口——找到字符串中所有字母异位词

简介: 【算法】滑动窗口——找到字符串中所有字母异位词

本节博客是对题目——找到字符串中所有字母异位词的从读题到代码实现以及优化的详细解读,有需要借鉴即可。



1.题目

题目链接:LINK

首先来解释一下什么是异位词,所谓“异位词”,即不要求字母顺序的字符串。

其实这个题目思路很快就可以想到,拿个left,right指针,使两者间距始终等于p字符串长度,再与p字符串对比一下就行了。

说起来这个思路那不就是“滑动窗口”嘛,因为两个指针都是从左到右移动的。

那异位怎么进行比较的呢?可以搞一个哈希数组进行依次比较即可。

2.滑动窗口 + 哈希数组

于是,我们可以写出下面的代码:

class Solution
{
public:
 bool check(int* p, int*s)
 {
    for(int i = 0;i < 128;i++)
    {
        if(p[i] != s[i])
        {
            return false;
        }
    }
    return true;
 }
 vector<int> findAnagrams(string s, string p) 
 {
    //统计一下p字符串的字符信息
    size_t len = p.size();
    int hash_p[128] = {0};
    for(int i = 0;i<len;i++)
    {
        hash_p[p[i]]++;
    }
    int n = s.size();
    int hash_s[128] = {0};
    vector<int> ret;
    //滑动窗口
    for(int right = 0,left = 0;right < n;right++)
    {
        //进窗口
        hash_s[s[right]]++;
        //判断,出窗口
        if(right - left + 1 > len)
        {
            hash_s[s[left]]--;
            left++;
        }
        //更新结果
        if(check(hash_p,hash_s) && right - left + 1 == len)
        {
            ret.push_back(left);
        }
    }
    return ret;
 }
};

实际上,题目中明确说只有小写字母,所以说可以把哈希数组搞成26个的:

class Solution
{
public:
    bool check(int* p, int* s)
    {
        for (int i = 0; i < 26; i++)
        {
            if (p[i] != s[i])
            {
                return false;
            }
        }
        return true;
    }
    vector<int> findAnagrams(string s, string p)
    {
        //统计一下p字符串的字符信息
        size_t len = p.size();
        int hash_p[26] = { 0 };
        for (int i = 0; i < len; i++)
        {
            hash_p[p[i] - 'a']++;
        }
        int n = s.size();
        int hash_s[26] = { 0 };
        vector<int> ret;
        //滑动窗口
        for (int right = 0, left = 0; right < n; right++)//"cbaebabacd"
        {
            //进窗口
            hash_s[s[right] - 'a']++;
            //判断,出窗口
            if (right - left + 1 > len)
            {
                hash_s[s[left] - 'a']--;
                left++;
            }
            //更新结果
            if (check(hash_p, hash_s) && right - left + 1 == len)
            {
                ret.push_back(left);
            }
        }
        return ret;
    }
};

3.异位词优化

虽然这样可以解题,不过问题是如果是比较的是比较多的字符呢?不仅仅是26的小写字母。我想如果这样比较,复杂度瞬间就会上来了。

所以,在比较异位词时,我们需要再优化一下:

思路大致是下面这样的,如下:

所以,可以优化为下面代码:

class Solution
{
public:
    vector<int> findAnagrams(string s, string p)
    {
        //统计一下p字符串的字符信息
        size_t len = p.size();
        int hash_p[26] = { 0 };
        for (int i = 0; i < len; i++)
        {
            hash_p[p[i] - 'a']++;
        }
        int n = s.size();
        int count = 0;//count标识有效字符的个数,即p字符串的长度
        int hash_s[26] = { 0 };
        vector<int> ret;
        //滑动窗口
        for (int right = 0, left = 0; right < n; right++)//"cbaebabacd"
        {
            //进窗口
            hash_s[s[right] - 'a']++;
            if(hash_s[s[right]-'a'] <= hash_p[s[right]-'a'])count++;//进窗口,维护有效字符个数
            //判断,出窗口
            if (right - left + 1 > len)
            {
                if(hash_s[s[left] - 'a'] <= hash_p[s[left] - 'a'])count--;//出窗口,维护有效字符个数
                hash_s[s[left] - 'a']--;
                left++;
            }
            //更新结果
            if (count == len)
            {
                ret.push_back(left);
            }
        }
        return ret;
    }
};

4.总结

其实总结一下来看,这个题目除了异位词问题之外也没什么东西,这个题目是一个典型的“固定长度的滑动窗口”,要解出来难度不大。


EOF

相关文章
|
2月前
|
算法
【算法】滑动窗口——最大连续1的个数
【算法】滑动窗口——最大连续1的个数
|
2月前
|
算法
【算法】滑动窗口——最小覆盖子串
【算法】滑动窗口——最小覆盖子串
|
2月前
|
算法
【算法】滑动窗口——将x减到0的最小操作数
【算法】滑动窗口——将x减到0的最小操作数
|
2月前
|
算法
【算法】滑动窗口——无重复字符的最长子串
【算法】滑动窗口——无重复字符的最长子串
|
2月前
|
算法
【算法】滑动窗口——长度最小的子数组
【算法】滑动窗口——长度最小的子数组
|
2月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
2月前
|
算法 容器
【算法】滑动窗口——串联所有单词的子串
【算法】滑动窗口——串联所有单词的子串
|
2月前
|
算法
【算法】滑动窗口——水果成篮
【算法】滑动窗口——水果成篮
|
28天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
28天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。
下一篇
无影云桌面