给你一个二进制串 s (一个只包含 0 和 1 的字符串),我们可以将 s 分割成 3 个 非空 字符串 s1, s2, s3 (s1
请你返回分割 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
方法一:模拟
要将字符串 s 分割成 3 个非空子字符串,且每个子字符串中的字符 1 的数目相同,显然字符串 s 中的字符 1 的数目必须是 3 的倍数,否则不可能满足 3 个子字符串中的字符 1 的数目相同。当字符串 s 中的字符 1 的数目确定时,每个子字符串中的字符 1 的数目也是确定的。
假设字符串 s 的长度为 n,字符串 s 中的字符 1 的数目为 m。遍历字符串 s,记录每个字符 1 的下标位置,并计算 m 的值。
如果 m 不是 3 的倍数,则不存在符合题目要求的分割 s 的方案,因此返回 0。
如果 m 是 3 的倍数,则分别考虑 m=0 和 m>0 的情况:
如果 m=0,则字符串 s 中的所有字符都为 0,因此可以在 s 的内部的任何位置进行分割。由于 s 的长度为 n,因此有 n-1 个分割位置,选择 2 个不同的分割位置即可将 s 分成 3 个非空子字符串,因此分割 s 的方案数为 \binom{n-1/2}=(n-1)(n-2)}{2。
如果 m>0,则每个子字符串都包含 m/3 个字符 1。假设 3 个子字符串从左到右依次为 s_1、s_2、s_3,其中 s_1 的最后一个字符 1 和 s_2 的第一个字符 1 之间的距离为 count}_1,s_2 的最后一个字符 1 和 s_3 的第一个字符 1 之间的距离为 count}_2,则对应的两个字符 1 之间的字符 0 的个数分别为 count}_1-1 和 count}_2-1,分别有 count}_1 和 count}_2 个分割位置,因此分割 s 的方案数为 count}_1 \times \textit{count}_2。
[sol1-Java]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { public int numWays(String s) { final int MODULO = 1000000007; List<Integer> ones = new ArrayList<Integer>(); int n = s.length(); for (int i = 0; i < n; i++) { if (s.charAt(i) == '1') { ones.add(i); } } int m = ones.size(); if (m % 3 != 0) return 0; if (m == 0) { long ways = (long) (n - 1) * (n - 2) / 2; return (int) (ways % MODULO); } else { int index1 = m / 3, index2 = m / 3 * 2; int count1 = ones.get(index1) - ones.get(index1 - 1); int count2 = ones.get(index2) - ones.get(index2 - 1); long ways = (long) count1 * count2; return (int) (ways % MODULO); } } }
|
[sol1-C++]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { private: static constexpr int MODULO = 1000000007;
public: int numWays(string s) { vector<int> ones; int n = s.size(); for (int i = 0; i < n; ++i) { if (s[i] == '1') { ones.push_back(i); } } int m = ones.size(); if (m % 3 != 0) { return 0; } if (m == 0) { long long ways = (long long)(n - 1) * (n - 2) / 2; return ways % MODULO; } else { int index1 = m / 3, index2 = m / 3 * 2; int count1 = ones[index1] - ones[index1 - 1]; int count2 = ones[index2] - ones[index2 - 1]; long long ways = (long long)count1 * count2; return ways % MODULO; } } };
|
[sol1-Python3]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 numWays(self, s: str) -> int: MODULO = 1000000007
ones = list() n = len(s) for i, digit in enumerate(s): if digit == "1": ones.append(i) m = len(ones) if m % 3 != 0: return 0 if m == 0: ways = (n - 1) * (n - 2) // 2 return ways % MODULO else: index1, index2 = m // 3, m // 3 * 2; count1 = ones[index1] - ones[index1 - 1] count2 = ones[index2] - ones[index2 - 1] ways = count1 * count2 return ways % MODULO
|
复杂度分析