- [Leetcode 3261. Count Substrings That Satisfy K-Constraint II](#Leetcode 3261. Count Substrings That Satisfy K-Constraint II)
- [1. 解题思路](#1. 解题思路)
- [2. 代码实现](#2. 代码实现)
1. 解题思路
这一题我们首先可以仿照题目3258的方式通过一个滑动窗口快速得到每一个位置作为起点时其对应的最大K-Constraint
的边界。
然后,我们通过如下query函数即可得到任意范围内的substring当中所有的满足K-Constraint
的子串个数:
python
def query(l, r):
ans = 0
for i in range(l, r+1):
ans += (min(boundaries[i], r+1) - i)
return ans
return [query(l, r) for l, r in queries]
但是,这个query函数的时间复杂度是 O ( N ) O(N) O(N),叠加上全部的query,整体的算法复杂度就会是 O ( M N ) O(MN) O(MN),时间复杂度过高,无法通过全部的测试样例,因此我们需要对query函数进行一下优化。
显然,如果不考虑这个min函数,那么query函数就可以快速地通过一个累积数组进行实现,只是这个min函数比较麻烦,因此我们对其进行一下拆分,首先找到min函数的这个分界点,然后左侧都满足min(boundaries[i], r+1) = boundaries[i]
,而右侧都满足min(boundaries[i], r+1) = r+1
,此时,我们就可以分成两个部分进行求解:
- 左侧: s = ∑ i = l k b i − i s = \sum\limits_{i=l}^{k} b_i - i s=i=l∑kbi−i
- 右侧: s = ∑ i = k + 1 r r + 1 − i s = \sum\limits_{i=k+1}^{r} r+1 - i s=i=k+1∑rr+1−i
前者我们可以通过累积数组来计算,后者我们直接通过等差数列即可求得。
由此,整体的query算法复杂度就降至 O ( 1 ) O(1) O(1)了。
2. 代码实现
给出python代码实现如下:
python
class Solution:
def countKConstraintSubstrings(self, s: str, k: int, queries: List[List[int]]) -> List[int]:
n = len(s)
i, j = 0, 0
cnt = defaultdict(int)
boundaries = [0 for _ in range(n)]
while i < n:
while j < n:
if cnt["0"] > k and cnt["1"] > k:
break
cnt[s[j]] += 1
j += 1
if cnt["0"] > k and cnt["1"] > k:
boundaries[i] = j-1
else:
boundaries[i] = j
cnt[s[i]] -= 1
i += 1
cnt = [b-i for i, b in enumerate(boundaries)]
cs = list(accumulate(cnt, initial=0))
def query(l, r):
i = max(bisect.bisect_right(boundaries, r), l)
ans = cs[i] - cs[l] + (r+1) * (r+1-i) - (r+i) * (r+1-i) // 2
return ans
return [query(l, r) for l, r in queries]
提交代码评测得到:耗时1470ms,占用内存72.9MB。