Python 子串置换复杂性

Python 子串置换复杂性,python,time-complexity,space-complexity,Python,Time Complexity,Space Complexity,刚才有一个关于Python实现的快速问题,关于子串置换的Leetcode问题,因为我是算法的主要新手: 给定两个字符串s1和s2,如果s2包含s1的置换,则编写一个函数返回true。换句话说,第一个字符串的一个排列是第二个字符串的子字符串 例1: Input: s1 = "ab" s2 = "eidbaooo" Output: True Explanation: s2 contains one permutation of s1 ("ba&quo

刚才有一个关于Python实现的快速问题,关于子串置换的Leetcode问题,因为我是算法的主要新手:

给定两个字符串s1和s2,如果s2包含s1的置换,则编写一个函数返回true。换句话说,第一个字符串的一个排列是第二个字符串的子字符串

例1:

Input: s1 = "ab" s2 = "eidbaooo"
Output: True
Explanation: s2 contains one permutation of s1 ("ba").
例2:

Input:s1= "ab" s2 = "eidboaoo"
Output: False
对于给定的一个解决方案,我相信下面的时间复杂度是O(n),但是时间复杂度是O(1)吗?此外,有人会有一个用于蛮力方法的Python实现的资源吗?谢谢大家!

from collections import Counter

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        s1_count, s2_count = Counter(s1), Counter(s2[:len(s1)])
        
        for i in range(len(s2)-len(s1)):
            if s1_count == s2_count: 
                return True
            
            if s2_count[s2[i]] == 1: 
                del s2_count[s2[i]]
            else: 
                s2_count[s2[i]] -= 1
            
            if s2[i+len(s1)] in s2_count: 
                s2_count[s2[i+len(s1)]] += 1
            else: 
                s2_count[s2[i+len(s1)]] = 1
                
        return s1_count == s2_count
        
sol = Solution()
print(sol.checkInclusion('ab', 'eidbaooo'))


    

我认为最优解是O(n),因为你需要搜索s2中s1的所有组合。下面是一个简明的python解决方案:

from itertools import permutations

def find_subs(s1,s2):
    perms = [''.join(p) for p in permutations(s1)] # create all possible permutations of s1
    for p in perms: 
        if p in s2: #search it in s2
            return True
    return False

find_subs('ab',"eidbaooo")

True

您自己的解决方案的时间复杂性似乎是O(n),因为时间与输入的长度成比例。O(1)意味着输入的大小无关紧要,这里的情况并非如此。根据inputvector的回答创建和搜索每一个可能的排列是您所要求的蛮力方法,当
len(s1)
超过10时,速度非常慢。这具有快速增长的时间复杂性O(n!)

我忍不住要打败你的算法。结果我不能。这是我的律师。在s1中,短字符串(最多6个字符)的速度稍微快一点。它具有O(n²)时间竞争性

def检查包括2(s1、s2):
i=-1
max_i=len(s2)-len(s1)+1
当i
所以,我试着优化你的,发现比较默认dict比计数器更快。并且将s2中的字符保存在临时变量中比多次获取它要快。这是速度的两倍,但这通常不计入时间复杂度。还是O(n)

从集合导入defaultdict
def检查包括3(s1、s2):
s1_计数,s2_计数=默认dict(int),默认dict(int)
对于范围内的i(len(s1)):
s1_计数[s1[i]+=1
s2_计数[s2[i]+=1
对于范围内的i(len(s2)-len(s1)):
如果s1_计数==s2_计数:
返回真值
old_c=s2[i]
如果s2_计数[old_c]==1:
删除s2_计数[旧的_c]
其他:
s2_计数[旧_c]=1
s2_计数[s2[i+len(s1)]]+=1
返回s1_计数==s2_计数

Ooh,那么就把它放到一个理解中吧。这仍然会使空间复杂度达到O(1),对吗?我不这么认为。正如示例中所提供的,s1和s2的“ab”和“eidbaooo”。在这种情况下,它可能更接近…O(n)。我认为…你不应该考虑一个特定输入的复杂性。顺便说一句,在你的例子中有一个问题,两个输入都是ab,谢谢。也许应该是“abb”?这里有一个问题的链接,它被逐字复制:非常好!很抱歉,我对这一领域仍然很陌生,但是枚举操作会不会将您的方法的时间复杂度提高到O(n),或者是其他原因?@ZapRowsdower您是对的。你的更快。我对它的理解被提升到了O(n*n)。@ZapRowsdower,但我成功地优化了您的解决方案:)我一直在浏览如何将dict实现嵌入其中,所以这种方法非常简洁。时间复杂度为O(2n),空间复杂度为O(n),我不确定。我认为我的优化只解决了python库中的一些怪癖,在复杂性方面与您的没有什么不同。实际上,因为函数有两个参数,所以compexity也应该有两个参数。对于n=len(s1)和m=len(s2),蛮力是O(n!·m),你和我的优化是O(n+m),我的第一次尝试类似于O(n·m)。说到太空,我认为蛮力需要O(n!+m),其他的可能需要O(n)