LeetCode 题解工作台

统计满足 K 约束的子字符串数量 II

给你一个 二进制 字符串 s 和一个整数 k 。 另给你一个二维整数数组 queries ,其中 queries[i] = [l i , r i ] 。 如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束 : 字符串中 0 的数量最多为 k 。 字符串中 1 的数量最多为 k 。…

category

5

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

困难 · 二分·搜索·答案·空间

bolt

答案摘要

我们用两个变量 和 分别记录当前窗口内的 和 的个数,指针 和 分别标识窗口的左右边界。用一个数组 记录每个位置 右边第一个不满足 约束的位置,初始时 $d[i] = n$。另外,用一个长度为 $n + 1$ 的前缀和数组 记录以前 个位置作为右边界的满足 约束的子字符串的个数。 当我们右移窗口时,如果窗口内的 和 的个数都大于 ,我们将 更新为 ,表示位置 右边第…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 二分·搜索·答案·空间 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个 二进制 字符串 s 和一个整数 k

另给你一个二维整数数组 queries ,其中 queries[i] = [li, ri]

如果一个 二进制字符串 满足以下任一条件,则认为该字符串满足 k 约束

  • 字符串中 0 的数量最多为 k
  • 字符串中 1 的数量最多为 k

返回一个整数数组 answer ,其中 answer[i] 表示 s[li..ri] 中满足 k 约束子字符串 的数量。

 

示例 1:

输入:s = "0001111", k = 2, queries = [[0,6]]

输出:[26]

解释:

对于查询 [0, 6]s[0..6] = "0001111" 的所有子字符串中,除 s[0..5] = "000111"s[0..6] = "0001111" 外,其余子字符串都满足 k 约束。

示例 2:

输入:s = "010101", k = 1, queries = [[0,5],[1,4],[2,3]]

输出:[15,9,3]

解释:

s 的所有子字符串中,长度大于 3 的子字符串都不满足 k 约束。

 

提示:

  • 1 <= s.length <= 105
  • s[i]'0''1'
  • 1 <= k <= s.length
  • 1 <= queries.length <= 105
  • queries[i] == [li, ri]
  • 0 <= li <= ri < s.length
  • 所有查询互不相同
lightbulb

解题思路

方法一:滑动窗口 + 前缀和

我们用两个变量 cnt0\textit{cnt0}cnt1\textit{cnt1} 分别记录当前窗口内的 0011 的个数,指针 iijj 分别标识窗口的左右边界。用一个数组 dd 记录每个位置 ii 右边第一个不满足 kk 约束的位置,初始时 d[i]=nd[i] = n。另外,用一个长度为 n+1n + 1 的前缀和数组 pre[i]\textit{pre}[i] 记录以前 ii 个位置作为右边界的满足 kk 约束的子字符串的个数。

当我们右移窗口时,如果窗口内的 0011 的个数都大于 kk,我们将 d[i]d[i] 更新为 jj,表示位置 ii 右边第一个不满足 kk 约束的位置。然后我们将 ii 右移一位,直到窗口内的 0011 的个数都不大于 kk。此时,我们可以计算出以 jj 为右边界的满足 kk 约束的子字符串的个数,即 ji+1j - i + 1,我们更新到前缀和数组中。

最后,对于每个查询 [l,r][l, r],我们首先找出 ll 右边第一个不满足 kk 约束的位置 pp,那么 p=min(r+1,d[l])p = \min(r + 1, d[l]),那么 [l,p1][l, p - 1] 的所有子字符串都满足 kk 约束,个数为 (1+pl)×(pl)/2(1 + p - l) \times (p - l) / 2,然后,我们计算以 [p,r][p, r] 为右边界的满足 kk 约束的子字符串的个数,即 pre[r+1]pre[p]\textit{pre}[r + 1] - \textit{pre}[p],最后将两者相加即可。

时间复杂度 O(n+m)O(n + m),空间复杂度 O(n)O(n)。其中 nnmm 分别为字符串 ss 的长度和查询数组 queries\textit{queries} 的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
    def countKConstraintSubstrings(
        self, s: str, k: int, queries: List[List[int]]
    ) -> List[int]:
        cnt = [0, 0]
        i, n = 0, len(s)
        d = [n] * n
        pre = [0] * (n + 1)
        for j, x in enumerate(map(int, s)):
            cnt[x] += 1
            while cnt[0] > k and cnt[1] > k:
                d[i] = j
                cnt[int(s[i])] -= 1
                i += 1
            pre[j + 1] = pre[j] + j - i + 1
        ans = []
        for l, r in queries:
            p = min(r + 1, d[l])
            a = (1 + p - l) * (p - l) // 2
            b = pre[r + 1] - pre[p]
            ans.append(a + b)
        return ans
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Candidate demonstrates understanding of sliding window and prefix sum techniques.

  • question_mark

    Candidate approaches binary search over valid answer space for query optimization.

  • question_mark

    Candidate focuses on reducing time complexity when processing large query sets.

warning

常见陷阱

外企场景
  • error

    Failing to optimize the solution for large inputs, resulting in slow runtime.

  • error

    Incorrectly managing query bounds or assuming substrings without proper validation.

  • error

    Misunderstanding the k-constraint or binary search, leading to incorrect counting of valid substrings.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Count substrings for other constraints, such as length or specific substring characters.

  • arrow_right_alt

    Generalize the problem to non-binary strings or extended constraint conditions.

  • arrow_right_alt

    Handle multiple queries simultaneously without preprocessing, testing for a less efficient solution.

help

常见问题

外企场景

统计满足 K 约束的子字符串数量 II题解:二分·搜索·答案·空间 | LeetCode #3261 困难