剑指 Offer II 014. 字符串中的变位词

题目

力扣

思路一 滑动窗口

变位词就是字符串中每个字符出现的次数都相同,但是排列顺序不同。统计s1中每个字母出现的次数,用大小为26的vector存储。再维护一个和s1长度相同的滑动窗口,逐渐往右移动,判断该滑动窗口中每个字符出现的次数是否与s1相同,子串中每个字符出现的次数用另一个大小为26的vector存储。

代码一

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        int m=s1.size(),n=s2.size();
        if(m>n) return false;
        vector<int> hash1(26),hash2(26);
        for(int i=0;i<m;i++){
            hash1[s1[i]-'a']++;
            hash2[s2[i]-'a']++;
        }
        if(hash1==hash2) return true;
        for(int i=m;i<n;i++){
            hash2[s2[i]-'a']++;
            hash2[s2[i-m]-'a']--;
            if(hash1==hash2) return true;
        }
        return false;
    }
};
class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        m,n=len(s1),len(s2)
        if(m>n):
            return False
        dict1=[0]*26
        dict2=[0]*26
        for i in range(m):
            dict1[ord(s1[i])-ord('a')]+=1
            dict2[ord(s2[i])-ord('a')]+=1
        if(dict1 == dict2):
            return True
        for i in range(m,n):
            dict2[ord(s2[i])-ord('a')]+=1
            dict2[ord(s2[i-m])-ord('a')]-=1
            if(dict1 == dict2):
                return True
        return False

优化思路

每次比较都需要比较两个vector,可以简化成用一个vector存储两个字符串的差异,并用diff变量存储两个字符串出现的字符有差异的个数。

优化代码

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        m,n=len(s1),len(s2)
        if(m>n):
            return False
        dict=[0]*26
        diff=0
        for i in range(m):
            dict[ord(s1[i])-ord('a')]-=1
            dict[ord(s2[i])-ord('a')]+=1
        for i in range(26):
            # diff += dict[i] if dict[i]>0 else -dict[i]
            if(dict[i]!=0):
                diff+=1

        if(diff==0):
            return True

        for i in range(m,n):
            a=ord(s2[i])-ord('a')
            b=ord(s2[i-m])-ord('a')
            if(a==b):
                continue

            if(dict[a]==0):
                diff+=1
            dict[a]+=1
            if(dict[a]==0):
                diff-=1

            if(dict[b]==0):
                diff+=1
            dict[b]-=1
            if(dict[b]==0):
                diff-=1
                
            if(diff==0):
                return True
        return False

思路二 双指针

和滑动窗口优化思路相似,首先遍历一遍s1,把s1中出现的字符在cnt数组中--。再遍历一遍s2,对于s2中出现的字符在cnt数组中++。如果出现cnt[x]大于0,就移动左指针,直到cnt[x]<=0。完成这些操作之后,如果right-left+1==n,那么这就是我们要找的子串。

代码二

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        m,n=len(s1),len(s2)
        cnt=[0]*26
        for i in range(m):
            cnt[ord(s1[i])-ord('a')]-=1
        left,right = 0,0
        while(right<n):
            x=ord(s2[right])-ord('a')
            cnt[x]+=1
            while(cnt[x]>0):
                cnt[ord(s2[left])-ord('a')]-=1
                left+=1
            if(right-left+1 == m):
                return True
            right+=1
        return False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值