438. Find All Anagrams in a String

本文介绍了一种高效算法,用于在给定的字符串中查找另一个字符串的所有字谜变位词的起始索引。通过使用固定大小的滑动窗口结合计数器列表,实现了快速匹配和更新,避免了不必要的重复计算。

Given a string s and a non-empty string p, find all the start indices of p’s anagrams in s.

Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.

The order of output does not matter.

Example 1:

**Input:**
s: "cbaebabacd" p: "abc"

**Output:**
[0, 6]

**Explanation:**
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".

Example 2:

**Input:**
s: "abab" p: "ab"

**Output:**
[0, 1, 2]

**Explanation:**
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".

开始的代码,会超时,负载度是 (n-k)k量级的。
复杂的主要是原因是14行的for循环里,每次都重新来定义一个新的字典。

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        ns=len(s)
        np=len(p)
        ans=[]
        d={}
        for i in p:
            d[i]=d.get(i,0)+1
        for i in range(ns-np+1):
            if self.constrast(s[i:i+np],d):
                ans.append(i)
        return ans

    def constrast(self,s,d):
        d1={}
        for i in s:
            d1[i]=d1.get(i,0)+1
        return d1==d

考虑,用不新的来定义字典来重做。
- 因为只有小写的字母,最多26个,考虑用长度为26的两个list代替上文的字典
- 每一次移动,s所对应的list做出相应的更新,这样就避免了最开始代码每次的重新构造。
96.24%

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        ns = len(s)
        np = len(p)
        ans = []
        if not ns or np>ns:return ans
        lists=[0]*26
        listp=[0]*26
        for i in range(np):
            listp[ord(p[i])-97] += 1
            lists[ord(s[i])-97] += 1
        for j in range(ns-np+1):
            if j:
                lists[ord(s[j-1]) - 97]-=1
                lists[ord(s[j-1+np]) - 97] += 1
            if listp==lists:
                ans.append(j)
        return ans

字典版本:81.31%

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        ns = len(s)
        np = len(p)
        ans = []
        if not ns or np>ns:return ans
        lists={}
        listp={}
        for i in range(np):
            listp[p[i]]=listp.get(p[i],0)+ 1
            lists[s[i]] =lists.get(s[i],0)+ 1
        for j in range(ns-np+1):
            if j:
                if lists[s[j-1]]==1:
                    lists.pop(s[j-1])
                else:
                    lists[s[j - 1]]-=1
                lists[s[j-1+np]] =lists.get(s[j-1+np],0)+ 1
            if listp==lists:
                ans.append(j)
        return ans
全排列是指将一个字符串中的字符进行重新排列,使得所有可能的排列都被考虑到。对于给定的字符串s,可以使用递归的方法来实现全排列。首先,选择一个字符作为排列的第一个字符,然后对剩余的字符进行全排列。这个过程可以通过不断交换字符的位置来实现。具体的代码实现可以参考以下示例代码: ```java public class StringPermutation { public void permutation(String s) { char\[\] array = s.toCharArray(); permutationHelper(array, 0, array.length - 1); } private void permutationHelper(char\[\] array, int start, int end) { if (start >= end) { System.out.println(new String(array)); } else { for (int i = start; i <= end; i++) { swap(array, i, start); permutationHelper(array, start + 1, end); swap(array, i, start); } } } private void swap(char\[\] array, int i, int j) { char temp = array\[i\]; array\[i\] = array\[j\]; array\[j\] = temp; } public static void main(String\[\] args) { StringPermutation permutation = new StringPermutation(); String s = "abc"; permutation.permutation(s); } } ``` 这段代码会输出字符串"abc"的所有全排列,即"abc"、"acb"、"bac"、"bca"、"cab"、"cba"。\[2\] 需要注意的是,全排列的时间复杂度为O(n!),其中n为字符串的长度。因此,对于较长的字符串,全排列可能会非常耗时。如果只需要判断一个字符串是否是另一个字符串的排列,可以使用类似于438. Find All Anagrams in a String的方法,只需要比较两个字符串中长度相同的子字符串所包含的字符是否一样即可。\[1\] #### 引用[.reference_title] - *1* [[LeetCode] 567. Permutation in String 字符串中的全排列](https://blog.csdn.net/weixin_30802171/article/details/97515238)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [字符串全排列问题](https://blog.csdn.net/weixin_41876155/article/details/81869743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值