📅  最后修改于: 2023-12-03 15:25:44.456000             🧑  作者: Mango
给定一个字符串s和一个整数k,找到s中的最长子串,使得该子串中的每个字符至少出现k次。
假设字符串s的长度为n,暴力算法时间复杂度为O(n^3),由于需要统计每个字符的出现次数,又需要循环遍历所有子串,因此最坏情况下,时间复杂度为O(n^2 * c),其中c代表字符集的大小。
分治算法的思路与暴力算法有点类似,但是通过分治算法的优化,可以优化时间复杂度,达到O(n*logn)。
假设字符串s的长度为n,分治算法时间复杂度为O(n*logn),其中统计计数器count的时间复杂度为O(n),递归过程的时间复杂度为O(logn)。
滑动窗口算法通过维护一个窗口,并在窗口内部移动,达到快速找到符合条件的最长子串的目的。
假设字符串s的长度为n,滑动窗口算法时间复杂度为O(26*n),由于常数项比较小,因此滑动窗口算法是最优的算法之一。
def is_legal(substr, k):
count = {}
for c in substr:
count[c] = count.get(c, 0) + 1
for c in count:
if count[c] < k:
return False
return True
def max_substring(s, k):
n = len(s)
max_len = 0
for i in range(n):
for j in range(i+1, n+1):
if is_legal(s[i:j], k):
max_len = max(max_len, j-i)
return max_len
def max_substring(s, k):
count = {}
for c in s:
count[c] = count.get(c, 0) + 1
left, right = 0, len(s)
for i in range(len(s)):
if count[s[i]] < k:
leftMax = max_substring(s[left:i], k) if (i - left) >= k else 0
rightMax = max_substring(s[i+1:right], k) if (right - i - 1) >= k else 0
return max(leftMax, rightMax)
return right - left
def max_substring(s, k):
count = {}
for c in s:
count[c] = count.get(c, 0) + 1
max_len = 0
left, right = 0, 0
n = len(s)
while right < n:
if count[s[right]] >= k:
right += 1
else:
max_len = max(max_len, right-left)
count[s[left]] -= 1
if count[s[left]] == 0:
del count[s[left]]
left += 1
return max(max_len, right-left)
本文介绍了三种求解最长符合条件的子串的算法,分别为暴力算法、分治算法和滑动窗口算法。这三种算法的时间复杂度从高到低分别为O(n^3)、O(n*logn)、O(n),因此在算法的选择上,应该优先选择滑动窗口算法。