LeetCode 438. 找到字符串中所有字母异位词(M)/ 839. (交换2个字母)相似字符串组(Hard)/ 567. s2 是否包含 s1 的排列(M) / 字母分组(滑窗)问题!!!

代码

class Solution:
    ### 1227 使用滑动窗口统计所有字母数量是否相同(100 ms,15.6 MB)
    def findAnagrams(self, s: str, p: str) -> List[int]:
        # 初始化两个字符串均为26位的列表(从a到z顺序排列),每一位的数量表示对应字母的数量
        ss, pp = [0] * 26, [0] * 26

        # 统计p中每一个字母的数量(使用ord来统计,即ASCII码)
        for i in p: pp[ord(i) - ord('a')] += 1

        # 统计s中第一个窗口的字母情况,窗口大小即为p的长度
        for i in s[: len(p)]: ss[ord(i) - ord('a')] += 1

        res = []
        # 初始化窗口左边界为0,右边界为len(p) - 1
        l, r = 0, len(p) - 1
        
        # 当右边界不越界时,进行循环(注意:r比右边界小一!)
        while r < len(s) - 1:
            # 若ss与pp中所有字母的数量相同,则是字母异位词,添加此时起始下标l
            if ss == pp: res.append(l)

            # 判断完当前l之后,去掉当前l所指向的字母,l加一右移(先ss减一,再l加一)
            ss[ord(s[l]) - ord('a')] -= 1
            l += 1

            # 判断完当前l之后,r加一右移(先r加一,再ss加一)
            r += 1            
            ss[ord(s[r]) - ord('a')] += 1

        # 注意:需要判断最后一个窗口的字符串是否为字母异位词!
        if ss == pp: res.append(l)

        return res

839. 相似字符串组

在这里插入图片描述

class Solution:
    def numSimilarGroups(self, strs: List[str]) -> int:
        n = len(strs)
        f = list(range(n))

        def find(x: int) -> int:
            if f[x] == x:
                return x
            f[x] = find(f[x])
            return f[x]
        
        def check(a: str, b: str) -> bool:
            num = 0
            for ac, bc in zip(a, b):
                if ac != bc:
                    num += 1
                    if num > 2:
                        return False
            return True
        
        for i in range(n):
            for j in range(i + 1, n):
                fi, fj = find(i), find(j)
                if fi == fj:
                    continue
                if check(strs[i], strs[j]):
                    f[fi] = fj
        
        ret = sum(1 for i in range(n) if f[i] == i)
        return ret

在这里插入图片描述

567. 字符串的排列(s2 是否包含 s1 的排列)

在这里插入图片描述

class Solution:
	# 滑窗
    def checkInclusion(self, s1: str, s2: str) -> bool:
        
        n = len(s2)
        # 定义滑动窗口的范围是 [left, right],闭区间,长度与s1相等
        left = 0
        right = len(s1) - 1

        # 统计 s1 中每个字符出现的次数
        counter1 = collections.Counter(s1)
        # 统计窗口s2[left, right - 1]内的元素出现的次数
        counter2 = collections.Counter(s2[0: right])

        while right < n:
            # 把 right 位置的元素放到 counter2 中
            counter2[s2[right]] += 1
            # 如果滑动窗口内各个元素出现的次数跟 s1 的元素出现次数完全一致,返回 True
            if counter1 == counter2:
                return True
            
            # 窗口向右移动前,把当前 left 位置的元素出现次数 - 1
            counter2[s2[left]] -= 1
            # 如果当前 left 位置的元素出现次数为 0, 需要从字典中删除,否则这个出现次数为 0 的元素会影响两 counter 之间的比较
            if counter2[s2[left]] == 0:
                del counter2[s2[left]]
            
            # 窗口向右移动
            left += 1
            right += 1

        return False
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值