Q 查询的给定范围内两个 1 之间的最大 0 计数
给定一个大小为N的二进制字符串S和一个由M对形式为{L, R}的查询组成的二维数组Q[][] ,每个查询的任务是找到位于两个1之间的0的最大数量在[L, R]范围内。
例子:
Input: S = “1001010”, Q[][] = {{0, 4}, {0, 5}}
Output: 2 3
Explanation:
The Queries are performed as per the following:
- Query(0, 4): Print 2 as there are maximum 2 0’s lying between the indices 0 and 3 in the substring over the range [0, 4] i.e., “10010”.
- Query(0, 5): Print 3 as there are maximum 3 0’s lying between the indices 0 and 5 in the substring over the range [0, 5] i.e “100101”.
Input: S = “111”, Q[][] = {{0, 2}}
Output: 0
朴素方法:解决给定问题的最简单方法是遍历给定的查询数组Q[][] ,并为每个查询通过迭代范围[L, R]打印任意两对1之间的最大0数.
时间复杂度: O(N*M)
辅助空间: O(1)
高效方法:上述方法可以使用前缀和数组的概念进行优化,这将导致查询的恒定时间计算。请按照以下步骤解决问题:
- 初始化两个数组leftBound[]和rightBound[]到 分别存储最近1的右侧0的计数和最近1左侧的0的计数。
- 初始化两个变量,比如count和total以更新数组leftBound[]和rightBound[] 。
- 遍历给定的字符串S ,如果当前字符为 ' 1 ',则将curr的值赋给变量total 。否则,将总计加1 ,然后将curr的值分配给rightBound[i] 。
- 将curr和totals的值更新为0 。
- 以相反的顺序遍历字符串,如果当前字符为 ' 1 ',则在每次迭代中将curr的值更新为total 。否则,将total的值增加1 ,然后将curr的值更新为 lefttBound[i] 。
- 完成上述步骤后,遍历给定的查询数组Q[][]并为每个查询打印(leftBound[Q[i][0]] + rightBound[Q[i][1]] – total)的值作为结果的最大数量0 。
下面是上述方法的实现:
C++
#include
using namespace std;
// Function to count the number of
// 0s lying between the two 1s for
// each query
void countOsBetween1s(string S, int N, int Q[][2])
{
// Stores count of 0's that are
// right to the most recent 1's
int leftBound[N];
// Stores count of 0's that are
// left to the most recent 1's
int rightBound[N];
// Stores the count of zeros
// in a prefix/suffix of array
int count = 0;
// Stores the count of total 0s
int total = 0;
// Traverse the string S
for (int i = 0; i < N; i++) {
// If current character is
// '1'
if (S[i] == '1') {
count = total;
}
// Otherwise
else if (S[i] == '0') {
total++;
}
// Update the rightBound[i]
rightBound[i] = count;
}
// Update count and total to 0
count = 0;
total = 0;
// Traverse the string S in
// reverse manner
for (int i = N - 1; i >= 0; i--) {
// If current character is
// '1'
if (S[i] == '1') {
count = total;
}
// Otherwise
else if (S[i] == '0') {
total++;
}
// Update the leftBound[i]
leftBound[i] = count;
}
// Traverse given query array
for (int q = 0; q < 2; q++) {
int L = Q[q][0];
int R = Q[q][1];
// Update the value of count
count = leftBound[L] + rightBound[R] - total;
// Print the count as the
// result to the current
// query [L, R]
cout << count << " ";
}
}
// Driver Code
int main()
{
string S = "1001010";
int Q[][2] = { { 0, 4 }, { 0, 5 } };
int N = S.length();
countOsBetween1s(S, N, Q);
return 0;
}
// This code is contributed by Potta Lokesh
Java
// Java program for the above approach
import java.lang.*;
import java.util.*;
class GFG {
// Function to count the number of
// 0s lying between the two 1s for
// each query
static void countOsBetween1s(
String S, int N, int[][] Q)
{
// Stores count of 0's that are
// right to the most recent 1's
int[] leftBound = new int[N];
// Stores count of 0's that are
// left to the most recent 1's
int[] rightBound = new int[N];
// Stores the count of zeros
// in a prefix/suffix of array
int count = 0;
// Stores the count of total 0s
int total = 0;
// Traverse the string S
for (int i = 0; i < N; i++) {
// If current character is
// '1'
if (S.charAt(i) == '1') {
count = total;
}
// Otherwise
else if (S.charAt(i) == '0') {
total++;
}
// Update the rightBound[i]
rightBound[i] = count;
}
// Update count and total to 0
count = 0;
total = 0;
// Traverse the string S in
// reverse manner
for (int i = N - 1; i >= 0; i--) {
// If current character is
// '1'
if (S.charAt(i) == '1') {
count = total;
}
// Otherwise
else if (S.charAt(i) == '0') {
total++;
}
// Update the leftBound[i]
leftBound[i] = count;
}
// Traverse given query array
for (int q = 0; q < Q.length; q++) {
int L = Q[q][0];
int R = Q[q][1];
// Update the value of count
count = leftBound[L] + rightBound[R] - total;
// Print the count as the
// result to the current
// query [L, R]
System.out.print(count + " ");
}
}
// Driver Code
public static void main(String[] args)
{
String S = "1001010";
int Q[][] = { { 0, 4 }, { 0, 5 } };
int N = S.length();
countOsBetween1s(S, N, Q);
}
}
Python3
# Function to count the number of
# 0s lying between the two 1s for
# each query
def countOsBetween1s(S, N, Q):
# Stores count of 0's that are
# right to the most recent 1's
leftBound = [0]*N
# Stores count of 0's that are
# left to the most recent 1's
rightBound = [0]*N
# Stores the count of zeros
# in a prefix/suffix of array
count = 0
# Stores the count of total 0s
total = 0
# Traverse the string S
for i in range(N):
# If current character is
# '1'
if (S[i] == '1'):
count = total
# Otherwise
elif (S[i] == '0'):
total += 1
# Update the rightBound[i]
rightBound[i] = count
# Update count and total to 0
count = 0
total = 0
# Traverse the string S in
# reverse manner
for i in range(N - 1, -1, -1):
# If current character is
# '1'
if (S[i] == '1'):
count = total
# Otherwise
elif (S[i] == '0'):
total += 1
# Update the leftBound[i]
leftBound[i] = count
# Traverse given query array
for q in range(2):
L = Q[q][0]
R = Q[q][1]
# Update the value of count
count = leftBound[L] + rightBound[R] - total
# Print the count as the
# result to the current
# query [L, R]
print(count, end=" ")
# Driver Code
if __name__ == "__main__":
S = "1001010"
Q = [[0, 4], [0, 5]]
N = len(S)
countOsBetween1s(S, N, Q)
# This code is contributed by ukasp.
C#
// C# program for the above approach
using System;
public class GFG {
// Function to count the number of
// 0s lying between the two 1s for
// each query
static void countOsBetween1s(
String S, int N, int[,] Q)
{
// Stores count of 0's that are
// right to the most recent 1's
int[] leftBound = new int[N];
// Stores count of 0's that are
// left to the most recent 1's
int[] rightBound = new int[N];
// Stores the count of zeros
// in a prefix/suffix of array
int count = 0;
// Stores the count of total 0s
int total = 0;
// Traverse the string S
for (int i = 0; i < N; i++) {
// If current character is
// '1'
if (S[i] == '1') {
count = total;
}
// Otherwise
else if (S[i] == '0') {
total++;
}
// Update the rightBound[i]
rightBound[i] = count;
}
// Update count and total to 0
count = 0;
total = 0;
// Traverse the string S in
// reverse manner
for (int i = N - 1; i >= 0; i--) {
// If current character is
// '1'
if (S[i] == '1') {
count = total;
}
// Otherwise
else if (S[i] == '0') {
total++;
}
// Update the leftBound[i]
leftBound[i] = count;
}
// Traverse given query array
for (int q = 0; q < Q.GetLength(0); q++) {
int L = Q[q,0];
int R = Q[q,1];
// Update the value of count
count = leftBound[L] + rightBound[R] - total;
// Print the count as the
// result to the current
// query [L, R]
Console.Write(count + " ");
}
}
// Driver Code
public static void Main(String[] args)
{
String S = "1001010";
int [,]Q = { { 0, 4 }, { 0, 5 } };
int N = S.Length;
countOsBetween1s(S, N, Q);
}
}
// This code is contributed by Amit Katiyar
Javascript
输出:
2 3
时间复杂度: O(N + M)
辅助空间: O(N)