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

[438.找到字符串中所有字母异位词](438. 找到字符串中所有字母异位词 - 力扣(LeetCode))

思路一:采用滑动窗口法

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        s_len, p_len = len(s), len(p)#分别为s_len,p_len附上长度
        
        if s_len < p_len:#如果字串大于主串则返回空列表
            return []

        ans = []
        s_count = [0] * 26
        p_count = [0] * 26
        for i in range(p_len):
            s_count[ord(s[i]) - 97] += 1#将元素转化为0~25,a的ASCLL值为97
            p_count[ord(p[i]) - 97] += 1

        if s_count == p_count:
            ans.append(0)#上述代码判断s中前len(p)个字符是否是字母异位词

        for i in range(s_len - p_len):
            s_count[ord(s[i]) - 97] -= 1
            s_count[ord(s[i + p_len]) - 97] += 1
            #消去上个窗口的起始的字符计数,相当于以窗口大小为len(p)在主串上移动
            if s_count == p_count:
                ans.append(i + 1)
			#若移动窗口后s_count仍等于p_count那么对应的起始索引为当前字符的下一个字符
        return ans
作者:力扣官方题解

来源:力扣(LeetCode)

这段代码是一个名为Solution的类中的一个方法,该方法用于查找字符串s中所有与字符串p为异位词(anagram)的子串的起始索引。异位词是指两个字符串中的字符相同,但顺序不同。

  1. 首先,获取字符串sp的长度,分别存储在变量s_lenp_len中。
  2. 如果s的长度小于p的长度,那么不可能存在长度大于s的子串是p的异位词,因此直接返回空列表。
  3. 初始化一个空列表ans,用于存储找到的异位词子串的起始索引。
  4. 创建两个长度为26的列表s_countp_count,用于统计字符串sp中每个字母出现的次数。这里假设输入字符串只包含小写字母。
  5. 遍历字符串p,更新p_count列表,统计每个字母出现的次数。
  6. 遍历字符串s的前p_len个字符,更新s_count列表,统计每个字母出现的次数。
  7. 如果此时s_countp_count相等,说明找到了一个异位词子串,将起始索引0添加到ans列表中。
  8. 从第p_len个字符开始遍历字符串s,每次移动一位,同时更新s_count列表:
    • 减去当前位置字符的计数
    • 加上下一个位置字符的计数
  9. 每次更新后,检查s_countp_count是否相等,如果相等,说明找到了一个异位词子串,将当前位置加1后添加到ans列表中。
  10. 最后返回ans列表,包含了所有找到的异位词子串的起始索引。

思路二:取每种结果进行判断(时间复杂度高,时间超了)

class Solution:
    def findAnagrams(self, s, p):
        list_p=list(p)
        list_p.sort()
        list_index=[]
        for i in range(len(s)):
            list_s=list(s[i:i+len(p)])
            list_s.sort()
            if list_s==list_p:
                list_index.append(i)
        return list_index

![](C:\Users\23613\Pictures\Screenshots\屏幕截图 2024-07-02 095033.png)

优化的滑动窗口算法

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        s_len, p_len = len(s), len(p)

        if s_len < p_len:
            return []

        ans = []
        count = [0] * 26
        for i in range(p_len):
            count[ord(s[i]) - 97] += 1
            count[ord(p[i]) - 97] -= 1

        differ = [c != 0 for c in count].count(True)#计算c中初始情况下不为0的个数

        if differ == 0:
            ans.append(0)#差异为0

        for i in range(s_len - p_len):
            
            if count[ord(s[i]) - 97] == 1: 
                differ -= 1
                 # 说明s[i]不是p中的字符,那么窗口移动则需先消除s[i]对differ的影响
            elif count[ord(s[i]) - 97] == 0:  
                differ += 1
                # 说明s[i]是p中的字符,那么窗口移动则需先消除s[i]对differ的影响
                
            count[ord(s[i]) - 97] -= 1#去除这个字符对列表count影响

            if count[ord(s[i + p_len]) - 97] == -1:  
                differ -= 1
                # 说明s[i + p_len]在p中,differ-1
            elif count[ord(s[i + p_len]) - 97] == 0:  
                differ += 1
                # 说明s[i + p_len]可能与之前的字符重复,或者不在p中
            count[ord(s[i + p_len]) - 97] += 1#代表s[i + p_len]已经在窗口中
            
            if differ == 0:
                ans.append(i + 1)

        return ans
作者:力扣官方题解

来源:力扣(LeetCode)

这段代码是一个名为 Solution 的类中的一个方法,该方法用于寻找字符串 s 中所有与字符串 p 为异位词(anagram)的子串的起始索引。异位词是指两个字符串中的字符相同,但顺序不同。

代码的主要逻辑如下:

  1. 首先检查输入字符串 s 的长度是否小于字符串 p 的长度,如果是,则直接返回空列表,因为无法在较短的字符串中找到长度大于它的异位词。

  2. 初始化一个长度为 26 的计数数组 count,用于统计每个字母在字符串 p 中出现的次数。同时,将字符串 s 的前 p_len 个字符对应的计数减一,以便于后续计算窗口内字母的数量差异。

  3. 计算初始窗口内字母数量的差异 differ,即 count 数组中非零元素的数量。如果 differ 为零,说明当前窗口内的字母分布与字符串 p 相同,因此将起始索引 0 添加到结果列表 ans 中。

  4. 遍历字符串 s,每次移动窗口一位,并更新计数数组 count 以及字母数量差异 differ。具体来说,对于窗口左侧即将离开的字符 s[i],如果其计数从负数变为正数或从正数变为零,说明该字符的数量差异发生了变化,需要相应地更新 differ。对于窗口右侧新加入的字符 s[i + p_len],同样进行类似的操作。

  5. 当窗口内字母数量差异 differ 为零时,说明当前窗口内的字母分布与字符串 p 相同,因此将当前窗口的起始索引 i + 1 添加到结果列表 ans 中。

  6. 最后返回结果列表 ans,包含了所有满足条件的子串的起始索引。

Posted on 2024-07-02 10:07  想要成为算法糕手  阅读(85)  评论(0)    收藏  举报