📌  相关文章
📜  计算将二进制字符串拆分为三个计数为零的子字符串的方法

📅  最后修改于: 2021-05-06 23:46:26             🧑  作者: Mango

给定二进制字符串str ,任务是计算将给定字符串拆分为三个具有0 s的不重叠子字符串的方式的总数。

例子:

方法:要解决此问题,想法是使用哈希的概念。以下是解决问题的步骤:

  1. 遍历字符串并计算零的总数,并将其存储在变量中,例如total_count
  2. 使用Hashmap(例如map )来存储累积总和0的频率。
  3. total_count / 3初始化变量k ,该变量表示每个分区中所需的0数。
  4. 初始化变量ressum来存储分别拆分字符串的方式数量和0 s的累积和。
  5. 如果当前字符为0 ,则迭代给定的字符串并增加总和
  6. 如果sum = 2k并且k在地图上存在,则通过map [k]增加res
  7. 更新地图中总和的频率。
  8. 最后返回res
  9. 如果total_count无法被3整除,则返回0。

下面是上述方法的实现:

C++
// C++ implementation for the above approach
#include
using namespace std;
 
// Function to return ways to split
// a string into three  parts
// with the equal number of 0
int count(string s)
{
     
    // Store total count of 0s
    int cnt = 0;
 
    // Count total no. of 0s
    // character in given string
    for(char c : s)
    {
        cnt += c == '0' ? 1 : 0;
    }
 
    // If total count of 0
    // character is not
    // divisible by 3
    if (cnt % 3 != 0)
        return 0;
 
    int res = 0, k = cnt / 3, sum = 0;
 
    // Initialize mp to store
    // frequency of k
    map mp;
 
    // Traverse string to find
    // ways to split string
    for(int i = 0; i < s.length(); i++)
    {
         
        // Increment count if 0 appears
        sum += s[i] == '0' ? 1 : 0;
 
        // Increment result if sum equal to
        // 2*k and k exists in mp
        if (sum == 2 * k && mp.find(k) != mp.end() &&
            i < s.length() - 1 && i > 0)
        {
            res += mp[k];
        }
         
        // Insert sum in mp
        mp[sum]++;
    }
     
    // Return result
    return res;
}
 
// Driver Code
int main()
{
     
    // Given string
    string str = "01010";
  
    // Function call
    cout << count(str);
}
 
// This code is contributed by rutvik_56


Java
// Java implementation for the above approach
 
import java.util.*;
import java.lang.*;
 
class GFG {
 
    // Function to return ways to split
    // a string into three  parts
    // with the equal number of 0
    static int count(String s)
    {
        // Store total count of 0s
        int cnt = 0;
 
        // Count total no. of 0s
        // character in given string
        for (char c : s.toCharArray()) {
            cnt += c == '0' ? 1 : 0;
        }
 
        // If total count of 0
        // character is not
        // divisible by 3
        if (cnt % 3 != 0)
            return 0;
 
        int res = 0, k = cnt / 3, sum = 0;
 
        // Initialize map to store
        // frequency of k
        Map map = new HashMap<>();
 
        // Traverse string to find
        // ways to split string
        for (int i = 0; i < s.length(); i++) {
 
            // Increment count if 0 appears
            sum += s.charAt(i) == '0' ? 1 : 0;
 
            // Increment result if sum equal to
            // 2*k and k exists in map
            if (sum == 2 * k && map.containsKey(k)
                && i < s.length() - 1 && i > 0) {
                res += map.get(k);
            }
 
            // Insert sum in map
            map.put(sum,
                    map.getOrDefault(sum, 0) + 1);
        }
 
        // Return result
        return res;
    }
    // Driver Code
    public static void main(String[] args)
    {
        // Given string
        String str = "01010";
 
        // Function call
        System.out.println(count(str));
    }
}


Python3
# Python3 implementation for
# the above approach
 
# Function to return ways to split
# a string into three  parts
# with the equal number of 0
def count(s):
 
    # Store total count of 0s
    cnt = 0
 
    # Count total no. of 0s
    # character in given string
    for c in s:
        if c == '0':
            cnt += 1
 
    # If total count of 0
    # character is not
    # divisible by 3
    if (cnt % 3 != 0):
        return 0
 
    res = 0
    k = cnt // 3
    sum = 0
 
    # Initialize map to store
    # frequency of k
    mp = {}
 
    # Traverse string to find
    # ways to split string
    for i in range(len(s)):
 
        # Increment count if 0 appears
        if s[i] == '0':
            sum += 1
 
        # Increment result if sum equal to
        # 2*k and k exists in map
        if (sum == 2 * k and k in mp and
            i < len(s) - 1 and i > 0):
            res += mp[k]
 
        # Insert sum in map
        if sum in mp:
            mp[sum] += 1
        else:
            mp[sum] = 1
             
    # Return result
    return res
 
# Driver Code
if __name__ == "__main__":
 
    # Given string
    st = "01010"
 
    # Function call
    print(count(st))
     
# This code is contributed by Chitranayal


C#
// C# implementation for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to return ways to split
// a string into three parts
// with the equal number of 0
static int count(String s)
{
     
    // Store total count of 0s
    int cnt = 0;
 
    // Count total no. of 0s
    // character in given string
    foreach(char c in s.ToCharArray())
    {
        cnt += c == '0' ? 1 : 0;
    }
 
    // If total count of 0
    // character is not
    // divisible by 3
    if (cnt % 3 != 0)
        return 0;
 
    int res = 0, k = cnt / 3, sum = 0;
 
    // Initialize map to store
    // frequency of k
    Dictionary map = new Dictionary();
 
    // Traverse string to find
    // ways to split string
    for(int i = 0; i < s.Length; i++)
    {
         
        // Increment count if 0 appears
        sum += s[i] == '0' ? 1 : 0;
 
        // Increment result if sum equal to
        // 2*k and k exists in map
        if (sum == 2 * k && map.ContainsKey(k) &&
            i < s.Length - 1 && i > 0)
        {
            res += map[k];
        }
 
        // Insert sum in map
        if(map.ContainsKey(sum))
            map[sum] = map[sum] + 1;
        else
            map.Add(sum, 1);
    }
 
    // Return result
    return res;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Given string
    String str = "01010";
 
    // Function call
    Console.WriteLine(count(str));
}
}
 
// This code is contributed by Amit Katiyar


C++
// C++ program for above approach
#include 
using namespace std;
 
// Function to calculate
// the number of ways to split
int splitstring(string s)
{
    int n = s.length();
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for (int i = 0; i < n; i++)
        if (s[i] == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0, waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for (int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s[i] == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
int main()
{
    string s = "01010";
   
    // Function Call
    cout << "The number of ways to split is "
         << splitstring(s) << endl;
}
 
// this code is contributed by Arif


Java
// Java program for above approach
import java.util.*;
 
class GFG{
     
// Function to calculate
// the number of ways to split
static int splitstring(String s)
{
    int n = s.length();
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for(int i = 0; i < n; i++)
        if (s.charAt(i) == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0;
    int waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for(int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s.charAt(i) == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
public static void main(String args[])
{
    String s = "01010";
 
    // Function Call
    System.out.println("The number of " +
                       "ways to split is " +
                       splitstring(s));
}
}
 
// This code is contributed by Stream_Cipher


Python3
# Python3 program for above approach
 
# Function to calculate
# the number of ways to split
def splitstring(s):
 
    n = len(s)
 
    # Calculating the total
    # number of zeros
    zeros = 0
    for i in range(n):
        if s[i] == '0':
            zeros += 1
 
    # Case1
    # If total count of zeros is not
    # divisible by 3
    if zeros % 3 != 0:
        return 0
 
    # Case2
    # if total count of zeros
    # is zero
    if zeros == 0:
        return ((n - 1) *
                (n - 2)) // 2
 
    # Case3
    # General case
 
    # Number of zeros in each substring
    zerosInEachSubstring = zeros // 3
 
    # Initialising zero to the number of ways
    # for first and second cut
    waysOfFirstCut, waysOfSecondCut = 0, 0
 
    # Initializing the count
    count = 0
 
    # Traversing from the begining
    for i in range(n):
         
        # Incrementing the count
        # if the element is '0'
        if s[i] == '0':
            count += 1
 
        # Incrementing the ways for the
        # 1st cut if count is equal to
        # zeros required in each substring
        if (count == zerosInEachSubstring):
            waysOfFirstCut += 1
 
        # Incrementing the ways for the
        # 2nd cut if count is equal to
        # 2*(zeros required in each substring)
        elif (count == 2 * zerosInEachSubstring):
            waysOfSecondCut += 1
 
    # Total number of ways to split is
    # multiplication of ways for the 1st
    # and 2nd cut
    return waysOfFirstCut * waysOfSecondCut
 
# Driver code
s = "01010"
 
# Function call
print("The number of ways to split is", splitstring(s))
 
# This code is contributed by divyeshrabadiya07


C#
// C# program for above approach
using System.Collections.Generic;
using System;
 
class GFG{
     
// Function to calculate
// the number of ways to split
static int splitstring(string s)
{
    int n = s.Length;
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for(int i = 0; i < n; i++)
        if (s[i] == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0;
    int waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for(int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s[i] == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
public static void Main()
{
    string s = "01010";
 
    // Function call
    Console.WriteLine("The number of ways " +
                      "to split is " +
                      splitstring(s));
}
}
 
// This code is contributed by Stream_Cipher


输出
4






时间复杂度: O(N)
辅助空间: O(N)

高效的方法:

为了将输入字符串分成三部分,只需要两个剪切,这将给出三个子字符串-S1,S2和S3。每个子字符串将具有相等的0,即(总数0)/ 3。现在,从字符串的开头开始跟踪0的计数。一旦计数等于(总数0)/ 3,就进行第一次切割。同样,一旦计数为0等于2 *(总数1)/ 3,就进行第二次切割。

算法

  1. 计算0的数量。如果不能被3整除,则答案= 0。
  2. 如果计数为0,则每个子字符串将具有相等的’0’数,即零个数字’0’。因此,分割给定字符串的方法总数为选择2个位置以将字符串从n-1个位置中分割出来的组合数。对于第一个选择,我们有n-1个选择,对于第二个选择,我们有n-2个选择。因此,组合的总数为(n-1)*(n-2)。由于选择相同,因此将其除以2的阶乘。因此答案= ((n-1)*(n-2))/ 2。
  3. 从头开始遍历给定的字符串,并再次保持计数“ 0s”,如果计数达到(“ 0s”总数)/ 3,我们将开始累加第一次切割的方式。当计数达到2 *(“ 0s”总数)/ 3时,我们开始累积第二次切割的方式数。
  4. 答案是第一次切割和第二次切割的路数相乘。

下面是上述方法的实现:

C++

// C++ program for above approach
#include 
using namespace std;
 
// Function to calculate
// the number of ways to split
int splitstring(string s)
{
    int n = s.length();
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for (int i = 0; i < n; i++)
        if (s[i] == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0, waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for (int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s[i] == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
int main()
{
    string s = "01010";
   
    // Function Call
    cout << "The number of ways to split is "
         << splitstring(s) << endl;
}
 
// this code is contributed by Arif

Java

// Java program for above approach
import java.util.*;
 
class GFG{
     
// Function to calculate
// the number of ways to split
static int splitstring(String s)
{
    int n = s.length();
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for(int i = 0; i < n; i++)
        if (s.charAt(i) == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0;
    int waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for(int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s.charAt(i) == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
public static void main(String args[])
{
    String s = "01010";
 
    // Function Call
    System.out.println("The number of " +
                       "ways to split is " +
                       splitstring(s));
}
}
 
// This code is contributed by Stream_Cipher

Python3

# Python3 program for above approach
 
# Function to calculate
# the number of ways to split
def splitstring(s):
 
    n = len(s)
 
    # Calculating the total
    # number of zeros
    zeros = 0
    for i in range(n):
        if s[i] == '0':
            zeros += 1
 
    # Case1
    # If total count of zeros is not
    # divisible by 3
    if zeros % 3 != 0:
        return 0
 
    # Case2
    # if total count of zeros
    # is zero
    if zeros == 0:
        return ((n - 1) *
                (n - 2)) // 2
 
    # Case3
    # General case
 
    # Number of zeros in each substring
    zerosInEachSubstring = zeros // 3
 
    # Initialising zero to the number of ways
    # for first and second cut
    waysOfFirstCut, waysOfSecondCut = 0, 0
 
    # Initializing the count
    count = 0
 
    # Traversing from the begining
    for i in range(n):
         
        # Incrementing the count
        # if the element is '0'
        if s[i] == '0':
            count += 1
 
        # Incrementing the ways for the
        # 1st cut if count is equal to
        # zeros required in each substring
        if (count == zerosInEachSubstring):
            waysOfFirstCut += 1
 
        # Incrementing the ways for the
        # 2nd cut if count is equal to
        # 2*(zeros required in each substring)
        elif (count == 2 * zerosInEachSubstring):
            waysOfSecondCut += 1
 
    # Total number of ways to split is
    # multiplication of ways for the 1st
    # and 2nd cut
    return waysOfFirstCut * waysOfSecondCut
 
# Driver code
s = "01010"
 
# Function call
print("The number of ways to split is", splitstring(s))
 
# This code is contributed by divyeshrabadiya07

C#

// C# program for above approach
using System.Collections.Generic;
using System;
 
class GFG{
     
// Function to calculate
// the number of ways to split
static int splitstring(string s)
{
    int n = s.Length;
 
    // Calculating the total
    // number of zeros
    int zeros = 0;
    for(int i = 0; i < n; i++)
        if (s[i] == '0')
            zeros++;
 
    // Case1
    // If total count of zeros is not
    // divisible by 3
    if (zeros % 3 != 0)
        return 0;
 
    // Case2
    // if total count of zeros
    // is zero
    if (zeros == 0)
        return ((n - 1) * (n - 2)) / 2;
 
    // Case3
    // General case
 
    // Number of zeros in each substring
    int zerosInEachSubstring = zeros / 3;
 
    // Initialising zero to the number of ways
    // for first and second cut
    int waysOfFirstCut = 0;
    int waysOfSecondCut = 0;
 
    // Initializing the count
    int count = 0;
 
    // Traversing from the begining
    for(int i = 0; i < n; i++)
    {
         
        // Incrementing the count
        // if the element is '0'
        if (s[i] == '0')
            count++;
 
        // Incrementing the ways for the
        // 1st cut if count is equal to
        // zeros required in each substring
        if (count == zerosInEachSubstring)
            waysOfFirstCut++;
 
        // Incrementing the ways for the
        // 2nd cut if count is equal to
        // 2*(zeros required in each substring)
        else if (count == 2 * zerosInEachSubstring)
            waysOfSecondCut++;
    }
 
    // Total number of ways to split is
    // multiplication of ways for the 1st
    // and 2nd cut
    return waysOfFirstCut * waysOfSecondCut;
}
 
// Driver Code
public static void Main()
{
    string s = "01010";
 
    // Function call
    Console.WriteLine("The number of ways " +
                      "to split is " +
                      splitstring(s));
}
}
 
// This code is contributed by Stream_Cipher
输出
The number of ways to split is 4







时间复杂度:O(n)

空间复杂度:O(1)