LeetCode 题解工作台

分割字符串的方案数

给你一个二进制串 s (一个只包含 0 和 1 的字符串),我们可以将 s 分割成 3 个 非空 字符串 s1, s2, s3 (s1 + s2 + s3 = s)。 请你返回分割 s 的方案数,满足 s1,s2 和 s3 中字符 '1' 的数目相同。 由于答案可能很大,请将它对 10^9 + 7 …

category

2

题型

code_blocks

4

代码语言

hub

3

相关题

当前训练重点

中等 · 数学·string

bolt

答案摘要

我们先遍历字符串 ,统计其中字符 的个数 ,如果 不能被 整除,那么无法分割,直接返回 。如果 为 ,说明字符串中没有字符 ,我们可以在 个位置中任意选择两个位置,将字符串分割成三个子串,那么方案数就是 。 如果 $cnt \gt 0$,我们将 更新为 ,即每个子串中字符 的个数。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数学·string 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个二进制串 s  (一个只包含 0 和 1 的字符串),我们可以将 s 分割成 3 个 非空 字符串 s1, s2, s3 (s1 + s2 + s3 = s)。

请你返回分割 s 的方案数,满足 s1,s2 和 s3 中字符 '1' 的数目相同。

由于答案可能很大,请将它对 10^9 + 7 取余后返回。

 

示例 1:

输入:s = "10101"
输出:4
解释:总共有 4 种方法将 s 分割成含有 '1' 数目相同的三个子字符串。
"1|010|1"
"1|01|01"
"10|10|1"
"10|1|01"

示例 2:

输入:s = "1001"
输出:0

示例 3:

输入:s = "0000"
输出:3
解释:总共有 3 种分割 s 的方法。
"0|0|00"
"0|00|0"
"00|0|0"

示例 4:

输入:s = "100100010100110"
输出:12

 

提示:

  • s[i] == '0' 或者 s[i] == '1'
  • 3 <= s.length <= 10^5
lightbulb

解题思路

方法一:计数

我们先遍历字符串 ss,统计其中字符 11 的个数 cntcnt,如果 cntcnt 不能被 33 整除,那么无法分割,直接返回 00。如果 cntcnt00,说明字符串中没有字符 11,我们可以在 n1n-1 个位置中任意选择两个位置,将字符串分割成三个子串,那么方案数就是 Cn12C_{n-1}^2

如果 cnt>0cnt \gt 0,我们将 cntcnt 更新为 cnt3\frac{cnt}{3},即每个子串中字符 11 的个数。

接下来我们找到第一个子字符串的右边界的最小下标,记为 i1i_1,第一个子字符串的右边界的最大下标(不包含),记为 i2i_2;第二个子字符串的右边界的最小下标,记为 j1j_1,第二个子字符串的右边界的最大下标(不包含),记为 j2j_2。那么方案数就是 (i2i1)×(j2j1)(i_2-i_1) \times (j_2-j_1)

注意答案可能很大,需要对 109+710^9+7 取模。

时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。其中 nn 为字符串 ss 的长度。

相似题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution:
    def numWays(self, s: str) -> int:
        def find(x):
            t = 0
            for i, c in enumerate(s):
                t += int(c == '1')
                if t == x:
                    return i

        cnt, m = divmod(sum(c == '1' for c in s), 3)
        if m:
            return 0
        n = len(s)
        mod = 10**9 + 7
        if cnt == 0:
            return ((n - 1) * (n - 2) // 2) % mod
        i1, i2 = find(cnt), find(cnt + 1)
        j1, j2 = find(cnt * 2), find(cnt * 2 + 1)
        return (i2 - i1) * (j2 - j1) % (10**9 + 7)
speed

复杂度分析

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

面试官常问的追问

外企场景
  • question_mark

    Candidate shows an understanding of the need to first check divisibility by 3.

  • question_mark

    Candidate knows how to identify the positions of '1's efficiently.

  • question_mark

    Candidate considers how to count valid splits based on the positions of '1's.

warning

常见陷阱

外企场景
  • error

    Ignoring the requirement that the total number of '1's must be divisible by 3.

  • error

    Failing to account for strings that contain no '1's or have fewer than three '1's.

  • error

    Incorrectly calculating the number of valid splits by not considering all the possible ways to split the string.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    What if the string contains only '0's?

  • arrow_right_alt

    How would you approach the problem if the string could contain other characters besides '0' and '1'?

  • arrow_right_alt

    What optimizations can be made if we are allowed to split the string into more than three parts?

help

常见问题

外企场景

分割字符串的方案数题解:数学·string | LeetCode #1573 中等