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

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

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



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

相关文章
|
4月前
|
算法
【算法】滑动窗口——最大连续1的个数
【算法】滑动窗口——最大连续1的个数
|
4月前
|
算法
【算法】滑动窗口——最小覆盖子串
【算法】滑动窗口——最小覆盖子串
|
4月前
|
算法
【算法】滑动窗口——将x减到0的最小操作数
【算法】滑动窗口——将x减到0的最小操作数
|
2月前
|
算法
两个字符串匹配出最长公共子序列算法
本文介绍了最长公共子序列(LCS)问题的算法实现,通过动态规划方法求解两个字符串的最长公共子序列,并提供了具体的编程实现细节和示例。
89 1
两个字符串匹配出最长公共子序列算法
|
2月前
|
算法
条件运算符与条件if的姻缘,打擂台算法和大小写字母转换,if逻辑避坑
条件运算符与条件if的姻缘,打擂台算法和大小写字母转换,if逻辑避坑
27 1
|
4月前
|
算法 Java
掌握算法学习之字符串经典用法
文章总结了字符串在算法领域的经典用法,特别是通过双指针法来实现字符串的反转操作,并提供了LeetCode上相关题目的Java代码实现,强调了掌握这些技巧对于提升算法思维的重要性。
|
4月前
|
算法 容器
【算法】滑动窗口——串联所有单词的子串
【算法】滑动窗口——串联所有单词的子串
|
4月前
|
算法
【算法】滑动窗口——水果成篮
【算法】滑动窗口——水果成篮
|
2月前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
13天前
|
算法 数据安全/隐私保护 索引
OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度
本项目展示了在MATLAB 2022a环境下,通过选择映射(SLM)与相位截断星座图(PTS)技术有效降低OFDM系统中PAPR的算法实现。包括无水印的算法运行效果预览、核心程序及详尽的中文注释,附带操作步骤视频,适合研究与教学使用。