分割字符串的方案数
难度:
标签:
题目描述
代码结果
运行时间: 56 ms, 内存: 16.7 MB
/*
* 使用 Java Stream 的解法:
* 1. 计算总的 '1' 的数量。
* 2. 如果不是 3 的倍数,返回 0。
* 3. 通过流操作找到分割点并计算组合数。
*/
import java.util.stream.IntStream;
public class Solution {
public int numWays(String s) {
int MOD = 1000000007;
int totalOnes = (int)s.chars().filter(c -> c == '1').count();
if (totalOnes % 3 != 0) return 0;
if (totalOnes == 0) return (int)(((long)(s.length() - 1) * (s.length() - 2) / 2) % MOD);
int onesPerPart = totalOnes / 3;
int[] counts = {0, 0, 0}; // {count, first, second}
int onesSoFar = 0;
for (char c : s.toCharArray()) {
if (c == '1') onesSoFar++;
if (onesSoFar == onesPerPart) counts[0]++;
if (onesSoFar == onesPerPart + 1) counts[1]++;
if (onesSoFar == 2 * onesPerPart) counts[2]++;
}
return (int)(((long)counts[1] * (long)counts[2]) % MOD);
}
}
解释
方法:
首先,我们需要统计字符串中'1'的总数。如果'1'的总数不能被3整除,那么不可能等分成三个部分,直接返回0。如果没有'1',即字符串全为'0',则可以在任何两个'0'之间切割来形成三个部分,计算方式是组合数C(n-1, 2),其中n是字符串的长度。如果'1'的数量可以被3整除,我们计算每个部分应含有的'1'的数量,然后找到这些'1'在原字符串中的确切位置。具体地,我们需要计算第1/3和第2/3位置的'1'之间,以及第2/3和第3/3位置的'1'之间的'0'的数量,这些'0'可以灵活地分配到相邻的部分中。最后,将这两个间隔的长度相乘即可得到分割方案的总数。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在处理全为'0'的字符串时,为什么选择使用组合数C(n-1, 2)来计算分割方案数?
▷🦆
如何确保在统计字符串中'1'的总数时,不会漏掉任何一个'1',特别是当'1'紧挨着字符串边界时?
▷🦆
如果'1'的数量可以被3整除,为什么计算两个分割点之间可以移动的'0'的数量是正确的方法?这样的计算对结果的准确性有什么影响?
▷🦆
在确定第1/3和第2/3位置的'1'之间的'0'数量时,实际上是如何处理边界条件,例如避免数组越界的?
▷