leetcode1573. 分割字符串的方案数(Python3、c++)

文章目录

  • leetcode1573. 分割字符串的方案数
    • 方法:数学
      • 思路:
      • 代码:
        • Python3:
        • cpp:
      • 结果:

leetcode1573. 分割字符串的方案数

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

方法:数学

思路:

本题可以使用数学的方法进行求解。

有效的分割方案是将字符串分为3组,假设长度为n,即在中间的n-1个空中选择两个进行划分。分割之后的三个部分中,1的数量相等。

那么,我们需要根据字符串中1的数量不同,进行分情况讨论。

首先,遍历一遍字符串,计算出字符串中1的个数num,同时使用一个数组ones来保存每个1的下标。

根据1的个数num的不同,我们分情况讨论:

  • 如果num不能被3整除,那么肯定无法得到一个正确的分割方案,使得三个部分的1个数相等,因此直接返回0。
  • 如果num=0,那么整个字符串均为0,那么每个部分的1的个数均为0,则即为在n-1个空中选择两个位置分割,因此答案为 C n − 1 2 C_{n-1}^2 Cn12,直接返回。
  • 如果num可以被3整除且不为0,那么就可以分为三个部分,每个部分的1的数量为delta=num/3,我们从ones数组中找到第delta个1和第2 * delta个1的下标idx1和idx2。那么,第一个分割线应该在idx1和ones[delta+1]之间的空中,一共有ones[delta+1]-idx1种可能,同理第二个分割线应该在idx2和ones[2 * delta+1]之间的空中,一共有ones[2*delta+1]-idx2种可能,两者相乘即为答案。

代码:

Python3:

class Solution:
    def numWays(self, s: str) -> int:
        res = 0
        # 表示1的个数
        num = 0
        # 存放每个1的索引
        ones = []
        n = len(s)
        # 遍历字符串s,维护ones和num
        for i in range(n):
            if s[i] == '1':
                ones.append(i)
                num += 1
        # 如果1的数量不能整除,那么没有有效的分割方案数,直接返回0
        if num%3:
            return 0
        # 如果没有1,即全是0,相当于在n-1个空中任选两个位置分割。即C(n-1,2)
        elif num == 0:
            res = (n-1)*(n-2)//2
            return res%(1000000007)
        # 如果1的个数是3的倍数,每个部分需要有delta个1
        else:
            delta = num//3
            # idx1为第delta个1的下标,idx2是第2*delta个1的下标
            idx1 = ones[delta-1]
            idx2 = ones[delta*2-1]
            res = (ones[delta]-idx1)*(ones[2*delta]-idx2)
            return res%(1000000007)

cpp:

class Solution {
     
public:
    int numWays(string s) {
     
        long long res = 0,num = 0;
        // num表示1的个数
        // 存放每个1的索引
        vector<long long>ones;
        long long n = s.size();
        // 遍历字符串s,维护ones和num
        for (int i = 0; i < n; i++)
            if (s[i] == '1'){
     
                ones.push_back(i);
                num ++;
            }        
        // 如果1的数量不能整除,那么没有有效的分割方案数,直接返回0
        if (num%3)
            return 0;
        // 如果没有1,即全是0,相当于在n-1个空中任选两个位置分割。即C(n-1,2)
        else if (num == 0){
     
            res = (n-1)*(n-2)/2;
            return res%(1000000007);
        }   
        // 如果1的个数是3的倍数,每个部分需要有delta个1
        else{
     
            long long delta = num/3;
            // idx1为第delta个1的下标,idx2是第2*delta个1的下标
            long long idx1 = ones[delta-1];
            long long idx2 = ones[delta*2-1];
            res = (ones[delta]-idx1)*(ones[2*delta]-idx2);
            return res%(1000000007);
        }
            

    }
};

结果:

leetcode1573. 分割字符串的方案数(Python3、c++)_第1张图片

leetcode1573. 分割字符串的方案数(Python3、c++)_第2张图片

你可能感兴趣的:(Leetcode做题记录,字符串,python,leetcode,c++)