给定一个二进制字符串s ,任务是计算这样的子字符串的数量,其中1的计数严格大于0的计数。
例子
Input: S = “110011”
Output: 11
Explanation:
Substrings in which the count of 1’s is strictly greater than the count of 0’s are { S[0]}, {S[0], S[1]}, {S[0], S[2]}, {S[0], S[4]}, {S[0], S[5]}, {S[1], S[1]}, {S[1], S[5]}, {S[3], S[5]}, {S[4], S[4]}, {S[4], S[5]}, {S[5], S[5]}.
Input: S = “101”
Output: 3
朴素的方法:解决问题最简单的方法是生成所有子串,并计算每个子串中1和0的数量。增加包含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)