Leet Code 的第 1573 题, 分割字符串的方案数

427 阅读2分钟

Leet Code 的第 1573 题

分割字符串的方案数

Number of Ways to Split a String


题目:

给你一个二进制串 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


C++ 代码:

class Solution {
    const int P=1000000007;
    typedef long long ll;
    int a[100002];
public:
    int numWays(string s) {
        int n=s.size(),i,x,y;
        for(i=0;i<n;i++){
            a[i+1]=a[i]+(s[i]=='1');
        }
        if(a[n]%3){
            return 0;
        }
        if(!a[n]){
            return (ll)(n-1)*(n-2)/2%P;
        }
        for(i=x=y=0;i<n;i++)
        {
            if(a[i]==a[n]/3)x++;
            if(a[i]==a[n]/3*2)y++;
        }
        return (ll)x*y%P;
    }
};

解释:

该题目,分为三种情况:

1, 元素都是 0,排列组合,就可以了

  • 第一次分割,有 n - 1 中选择,

  • 第 2 次分割,有 n - 2 中选择,

再除以 2 ,去除重复

2, 元素有 0 有 1,1 的个数除 3,除不尽。 简单描述,就是,没戏

返回 0

3, 有戏。 元素有 0 有 1,1 的个数除 3,可以除尽。

用一个动态规划,

例子:

输入:s = "10101"

辅助数组 [ 0 , 1, 1, 2, 2, 3 ]

array[i] 的值,代表前 i - 1 个元素中,1 出现的次数

所以 array[string.length] 代表,字符串中有多少个 1,a[n]

  • 第一次分割, 可以有多少种,就是 array 中,有几个为 a[n] / 3

  • 第 2 次分割, 可以有多少种,就是 array 中,有几个为 a[n] * 2 / 3

两种分割的方式,各自独立变化,互不影响,

所以,总的分割方案数,就是直接乘起来,就好

PS:

动态规划,一般就是用空间,换时间

把用指针很难处理的操作,用简单的查表取代

PPS:

使用 Swift 实现同样的逻辑,性能很差, ...