📌  相关文章
📜  二进制字符串中 1 数多于 0 数的子串数

📅  最后修改于: 2021-09-16 11:14:01             🧑  作者: Mango

给定一个二进制字符串s ,任务是计算这样的子字符串的数量,其中1的计数严格大于0的计数。

例子

朴素的方法:解决问题最简单的方法是生成所有子串,并计算每个子串中10的数量。增加包含1 s 计数大于0 s 计数的那些子字符串的计数。最后,打印获得的计数。
时间复杂度:O(N 3 )
辅助空间: O(1)

高效方法:上述方法可以使用归并排序算法进行优化。请按照以下步骤操作:

  • 初始化一个数组,比如大小为n 的nums[] 其中n是字符串的长度。
  • 遍历字符串。如果s[i] == ‘1’ ,则将1存储在nums[i] 中。否则,设置nums[i] = -1
  • 更新pref[]以存储数组nums[] 的前缀和
  • 现在,问题简化为计算数组pref[]对 (i, j)的数量,其中pref[i] < pref[j]i < j ,这类似于从后面计算数组中的反转边。
  • 返回前缀和数组的反转次数作为最终答案。

下面是上述方法的实现。

C++14
// C++ program for the above approach
#include 
using namespace std;
 
// Function to merge two partitions
// such that the merged array is sorted
void merge(vector& v, int left,
           int mid, int right, int& inversions)
{
    vector temp(right - left + 1);
 
    int i = left;
    int j = mid + 1;
    int k = 0;
    int cnt = 0;
 
    while (i <= mid && j <= right) {
        if (v[i] <= v[j]) {
            temp[k++] = v[i++];
        }
        else {
            // Counting inversions
            inversions += (mid - i + 1);
 
            temp[k++] = v[j++];
        }
    }
 
    while (i <= mid)
        temp[k++] = v[i++];
 
    while (j <= right)
        temp[k++] = v[j++];
 
    k = 0;
    for (int a = left; a <= right; a++) {
        v[a] = temp[k++];
    }
}
 
// Function to implement merge sort
void mergeSort(vector& v, int left,
               int right, int& inversions)
{
    if (left < right) {
        int mid = (left + right) / 2;
 
        mergeSort(v, left, mid, inversions);
        mergeSort(v, mid + 1, right, inversions);
        merge(v, left, mid, right, inversions);
    }
}
 
// Function to calculate number of
// inversions in a given array
int CountInversions(vector& v)
{
    int n = v.size();
    int inversions = 0;
 
    // Calculate the number of inversions
    mergeSort(v, 0, n - 1, inversions);
 
    // Return the number of inversions
    return inversions;
}
 
// Function to count the number of
// substrings that contains more 1s than 0s
int getSubsCount(string& input)
{
    int n = input.length();
 
    vector nums(n);
 
    for (int i = 0; i < n; i++) {
        nums[i] = input[i] - '0';
 
        if (nums[i] == 0)
            nums[i] = -1;
    }
 
    // Stores the prefix sum array
    vector pref(n);
 
    int sum = 0;
 
    for (int i = 0; i < n; i++) {
        sum += nums[i];
        pref[i] = sum;
    }
 
    int cnt = 0;
 
    // Stores the count of valid substrings
    for (int i = 0; i < n; i++) {
        if (pref[i] > 0)
            cnt++;
    }
 
    reverse(pref.begin(), pref.end());
 
    int inversions = CountInversions(pref);
 
    int ans = cnt + inversions;
 
    return ans;
}
 
// Driver Code
int main()
{
 
    // Given Input
    string input = "101";
 
    // Function Call
    int ans = getSubsCount(input);
 
    cout << ans << endl;
 
    return 0;
}


Python3
# python 3 program for the above approach
 
# Function to merge two partitions
# such that the merged array is sorted
def merge(v, left,mid, right, inversions):
    temp = [0 for i in range(right - left + 1)]
 
    i = left
    j = mid + 1
    k = 0
    cnt = 0
 
    while (i <= mid and j <= right):
        if (v[i] <= v[j]):
            temp[k] = v[i]
            k += 1
            i += 1
 
        else:
            # Counting inversions
            inversions += (mid - i + 1)
 
            temp[k] = v[j]
            k += 1
            j += 1
 
    while (i <= mid):
        temp[k] = v[i]
        k += 1
        i += 1
 
    while (j <= right):
        temp[k] = v[j]
        k += 1
        j += 1
 
    k = 0
    for a in range(left,right+1,1):
        v[a] = temp[k]
        k += 1
 
# Function to implement merge sort
def mergeSort(v, left, right,inversions):
    if (left < right):
        mid = (left + right) // 2
 
        mergeSort(v, left, mid, inversions)
        mergeSort(v, mid + 1, right, inversions)
        merge(v, left, mid, right, inversions)
 
# Function to calculate number of
# inversions in a given array
def CountInversions(v):
    n = len(v)
    inversions = 0
 
    # Calculate the number of inversions
    mergeSort(v, 0, n - 1, inversions)
 
    # Return the number of inversions
    return inversions
 
# Function to count the number of
# substrings that contains more 1s than 0s
def getSubsCount(input):
    n = len(input)
 
    nums = [0 for i in range(n)]
 
    for i in range(n):
        nums[i] = ord(input[i]) - 48
 
        if (nums[i] == 0):
            nums[i] = -1
 
    # Stores the prefix sum array
    pref = [0 for i in range(n)]
 
    sum = 0
 
    for i in range(n):
        sum += nums[i]
        pref[i] = sum
 
    cnt = 0
 
    # Stores the count of valid substrings
    for i in range(n):
        if (pref[i] > 0):
            cnt += 1
     
    pref = pref[:-1]
 
    inversions = CountInversions(pref)
 
    ans = cnt + inversions + 1
 
    return ans
 
# Driver Code
if __name__ == '__main__':
   
    # Given Input
    input = "101"
 
    # Function Call
    ans = getSubsCount(input)
    print(ans)
     
    # This code is contributed by ipg2016107.


输出:
3

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