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。

相关推荐
bohu833 小时前
sentinel学习笔记1-为什么需要服务降级
笔记·学习·sentinel·滑动窗口
幼儿园口算大王3 天前
关于滑动窗口算法--最小替换字串长度
java·数据结构·算法·滑动窗口
DogDaoDao4 天前
leetcode 面试经典 150 题:长度最小的子数组
算法·leetcode·面试·双指针·滑动窗口·数据结构与算法·子数组
Espresso Macchiato7 天前
Leetcode 3389. Minimum Operations to Make Character Frequencies Equal
动态规划·leetcode hard·分类讨论·leetcode 3389·leetcode周赛428
GGBondlctrl8 天前
【Leetcode】滑动窗口算法-编程苍穹下划破数据暗夜的高效光弧
数据结构·算法·leetcode·滑动窗口·长度最小子数组·无重复字符长子串
Espresso Macchiato21 天前
Leetcode 3373. Maximize the Number of Target Nodes After Connecting Trees II
动态规划·leetcode hard·leetcode 3373·leetcode周赛426·树的遍历
呼啦啦啦啦啦啦啦啦1 个月前
刷题日常(移动零,盛最多水的容器,三数之和,无重复字符的最长子串)
算法·双指针·滑动窗口
做人不要太理性1 个月前
【算法一周目】滑动窗口(2)
c++·算法·leetcode·哈希算法·散列表·滑动窗口
Espresso Macchiato1 个月前
Leetcode 3354. Make Array Elements Equal to Zero
leetcode·累积数组·leetcode 3354·leetcode easy·leetcode周赛424
一直学习永不止步1 个月前
LeetCode题练习与总结:至少有 K 个重复字符的最长子串--395
java·算法·leetcode·字符串·滑动窗口·哈希表·分治