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 实现同样的逻辑,性能很差, ...