Leetcode 3261. Count Substrings That Satisfy K-Constraint II

  • [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。

相关推荐
HUIMU_1 天前
DAY20-新世纪DL(DeepLearning/深度学习)战士:终(目标检测/YOLO)3
深度学习·yolo·目标检测·滑动窗口·非极大值抑制·交并比·bouding box
蜡笔小柯南2 天前
每秒扛住10万请求?RedissonRateLimiter 分布式限流器详解
分布式·redisson·滑动窗口·ratelimiter
Dream it possible!4 天前
LeetCode 面试经典 150_滑动窗口_串联所有单词的子串(32_30_C++_困难)(滑动窗口:控制起点和滑动距离)
c++·leetcode·面试·滑动窗口
Q741_1479 天前
C++ 力扣 76.最小覆盖子串 题解 优选算法 滑动窗口 每日一题
c++·算法·leetcode·双指针·滑动窗口
Q741_14716 天前
C++ 力扣 438.找到字符串中所有字母异位词 题解 优选算法 滑动窗口 每日一题
c++·算法·leetcode·双指针·滑动窗口
Tisfy17 天前
LeetCode 837.新 21 点:动态规划+滑动窗口
数学·算法·leetcode·动态规划·dp·滑动窗口·概率
KarrySmile18 天前
Day8--滑动窗口与双指针--1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组
数据结构·算法·双指针·滑动窗口·不定长滑动窗口·最大连续1的个数·最长子数组
伟大的车尔尼18 天前
滑动窗口题目:字符串的排列
滑动窗口
崎岖Qiu1 个月前
leetcode1343:大小为K的子数组(定长滑动窗口)
java·算法·leetcode·力扣·滑动窗口
崎岖Qiu1 个月前
leetcode643:子数组最大平均数 I(滑动窗口入门之定长滑动窗口)
java·算法·leetcode·力扣·双指针·滑动窗口