JavaInterview JavaInterview
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)

『Java面试+Java学习』
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)
  • 指南
  • 简历

  • Java

  • 面试

  • 算法

  • algorithm
  • leetcode
JavaInterview.cn
2025-05-08
目录

分割字符串的方案数Java

文章发布较早,内容可能过时,阅读注意甄别。

# 题目

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

# 思路

定义常量 MOD,用于后续结果取模

# 解法

class Solution {
    // 定义常量 MOD,用于后续结果取模
    private static final int MOD = 1_000_000_007;

    public int numWays(String s) {
        int totalOnes = 0;
        
        // 统计字符串中 '1' 的总数
        for (char c : s.toCharArray()) {
            if (c == '1') totalOnes++;
        }

        // 如果 '1' 的总数不能被 3 整除,则无法分割成三个相同数量的 '1',直接返回 0
        if (totalOnes % 3 != 0) return 0;

        // 如果字符串中没有 '1',即 totalOnes == 0,所有字符都是 '0',可以通过组合数来计算分割方式
        if (totalOnes == 0) {
            int n = s.length();
            // 计算可以从 (n-1) 个位置中选择 2 个位置进行分割,即组合数 C(n-1, 2)
            return (int)((long)(n - 1) * (n - 2) / 2 % MOD);
        }

        // 每一部分的 '1' 数量
        int onesPerPart = totalOnes / 3;
        //分别表示可以进行第一次和第二次分割的方式数量。
        int firstSplitWays = 0, secondSplitWays = 0;
        int currentOnes = 0;  // 当前遍历过程中 '1' 的数量

        // 遍历字符串,计算第一次和第二次分割可能的方式数
        for (char c : s.toCharArray()) {
            if (c == '1') currentOnes++;  // 每遇到一个 '1',就增加 currentOnes 的计数

            // 如果 currentOnes 达到了每个部分应该包含的 '1' 数量,则可能成为第一次分割点
            if (currentOnes == onesPerPart) firstSplitWays++;

            // 如果 currentOnes 达到了两倍的 onesPerPart,则可能成为第二次分割点
            if (currentOnes == 2 * onesPerPart) secondSplitWays++;
        }
        //最终的分割方案数是第一次分割方式数 firstSplitWays 与第二次分割方式数 secondSplitWays 的乘积
        //乘法可能会造成溢出  结果对 MOD 取模
        return (int)((long)firstSplitWays * secondSplitWays % MOD);
    }
}

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
32
33
34
35
36
37
38
39
40
41
42
43
44

# 总结

  • 分析出几种情况,然后分别对各个情况实现
微信 支付宝
#Java
最近更新
01
1633. 各赛事的用户注册率 Java
07-13
02
1636. 按照频率将数组升序排序 Java
07-13
03
1640. 能否连接形成数组 Java
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 JavaInterview.cn
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式