Given a string S of size N, the task is to find the number of substrings of odd lengths that have a median equal to the Kth character of the string.
Examples:
Input: S = “ecadgg”, K = 4
Output: 4
Explanation: Character at 4th position in string is ‘d’.
Then there are 4 odd length substrings with ‘d’ as their median:
[d], [a, d, g], [e, c, a, d, g], therefore return 4 as the answer.Input: s = “abc”, K = 1
Output: 1
Explanation: Character at 1st position in string is ‘a’. Then there is only 1 odd length substring with ‘a’ as its median: [a] therefore return 1 as the answer.
Approach: To solve the problem follow the below idea:
Median is middle element. So smaller elements has to be equal to number of bigger elements, the desired substrings would be like (S[K]) or (2 elements on left and right), (4 elements on left and right), so on. . . [cannot take 1, 3 . . . because the substring should have odd length]
- We can maintain smaller and bigger arrays of length N and populate them.
- This helps us to find in range [i, j] count of smaller and bigger elements with respect to S[K].
- For S[K] to be median in the range [i, j], the number of characters smaller than S[K] should be equal to the number of characters greater than S[K] and the subarray should include S[K].
Note: We are considering 1based indexing of string for understanding but the actual implementation uses 0 based indexing.
Follow the steps to solve the problem:
- Create two vectors namely greater and smaller of size N.
- Traverse the string:
- Mark 1 in a smaller vector at ith position, if the character at that index is smaller than the Kth character of the string, and
- Mark 1 in a greater vector at the ith position if the character is greater than the Kth character of the string.
- Create a difference array that stores the difference of smaller and greater for each ith position.
- Use prefix sum on difference array to find valid subarrays. In valid subarrays, the sum will be 0.
- Use the prefix sum for the following three segments:
- start = 0 and end = N and store it in val1,
- start = 0 and end = K-1 store it in val2 and
- start = K and end = N and store it in val3.
- Use the prefix sum for the following three segments:
- In the end, return val1 – val2 – val3, which is the count of substrings with equally smaller and greater elements that contain Kth character.
Below is the implementation of the above approach.
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
// Function for finding the number of // sub strings in (start, end) where // sum of difference is zero int sum( int start, int end, vector< int >& v)
{ // STL map to store number of subarrays
// starting from index zero having
// particular value of sum.
unordered_map< int , int > prevSum;
int res = 0, currSum = 0;
for ( int i = start; i < end; i++) {
// Add current element to sum so far.
currSum += v[i];
// If currsum is equal to 0, then
// a new subarray is found.
// So increase count of subarrays.
if (currSum == 0)
res++;
if (prevSum.find(currSum) != prevSum.end())
res += (prevSum[currSum]);
// Add currsum value to count of
// different values of sum.
prevSum[currSum]++;
}
return res;
} // Function to find odd length substrings // whose median is equal to s[k-1] int numberOfSubstrings(string& s, int k)
{ int n = s.size();
// Initializing vectors for storing
// element is smaller or greater
// than median
vector< int > smaller(n, 0), greater(n, 0);
for ( int i = 0; i < n; i++) {
smaller[i] = s[i] < s[k - 1];
greater[i] = s[i] > s[k - 1];
}
// Declaring a vector to store
// difference of greater and smaller
// characters for each position
vector< int > diff(n, 0);
for ( int i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
// Substrings in (0 to n)
int val1 = sum(0, n, diff);
// Substrings in (0 to k-1)
int val2 = sum(0, k - 1, diff);
// Substrings in (k to n)
int val3 = sum(k, n, diff);
// Considering only those sub strings
// with difference 0 that
// contains s[k-1]
return val1 - val2 - val3;
} // Driver code int main()
{ string S = "ecadgg" ;
int K = 4;
// Function call
cout << numberOfSubstrings(S, K);
return 0;
} |
// Java code to implement the approach import java.io.*;
import java.util.*;
class GFG {
// Function for finding the number of
// sub strings in (start, end) where
// sum of difference is zero
public static int sum( int start, int end, int v[])
{
// STL map to store number of subarrays
// starting from index zero having
// particular value of sum.
HashMap<Integer, Integer> prevSum
= new HashMap<Integer, Integer>();
int res = 0 , currSum = 0 ;
for ( int i = start; i < end; i++) {
// Add current element to sum so far.
currSum += v[i];
// If currsum is equal to 0, then
// a new subarray is found.
// So increase count of subarrays.
if (currSum == 0 )
res++;
if (prevSum.containsKey(currSum)) {
res += prevSum.get(currSum);
prevSum.put(currSum,
prevSum.get(currSum) + 1 );
}
// Add currsum value to count of
// different values of sum.
prevSum.put(currSum, 1 );
}
return res;
}
// Function to find odd length substrings
// whose median is equal to s[k-1]
public static int numberOfSubstrings(String s, int k)
{
int n = s.length();
// Initializing vectors for storing
// element is smaller or greater
// than median
int smaller[] = new int [n];
int greater[] = new int [n];
for ( int i = 0 ; i < n; i++) {
smaller[i]
= (s.charAt(i) < s.charAt(k - 1 )) ? 1 : 0 ;
greater[i]
= (s.charAt(i) > s.charAt(k - 1 )) ? 1 : 0 ;
}
// Declaring a vector to store
// difference of greater and smaller
// characters for each position
int diff[] = new int [n];
for ( int i = 0 ; i < n; i++)
diff[i] = smaller[i] - greater[i];
// Substrings in (0 to n)
int val1 = sum( 0 , n, diff);
// Substrings in (0 to k-1)
int val2 = sum( 0 , k - 1 , diff);
// Substrings in (k to n)
int val3 = sum(k, n, diff);
// Considering only those sub strings
// with difference 0 that
// contains s[k-1]
return val1 - val2 - val3;
}
// Driver Code
public static void main(String[] args)
{
String S = "ecadgg" ;
int K = 4 ;
// Function call
System.out.print(numberOfSubstrings(S, K));
}
} // This code is contributed by Rohit Pradhan |
# Python code for the above approach # Function for finding the number of # sub strings in (start, end) where # sum of difference is zero def sum (start, end, v):
# STL map to store number of subarrays
# starting from index zero having
# particular value of sum.
prevSum = {};
res = 0
currSum = 0 ;
for i in range (start, end):
# Add current element to sum so far.
currSum + = v[i];
# If currsum is equal to 0, then
# a new subarray is found.
# So increase count of subarrays.
if (currSum = = 0 ):
res + = 1
if (currSum in prevSum):
res + = (prevSum[currSum]);
# Add currsum value to count of
# different values of sum.
if (currSum in prevSum):
prevSum[currSum] + = 1
else :
prevSum[currSum] = 1
return res;
# Function to find odd length substrings # whose median is equal to s[k-1] def numberOfSubstrings(s, k):
n = len (s)
# Initializing vectors for storing
# element is smaller or greater
# than median
smaller = [ 0 ] * n
greater = [ 0 ] * n
for i in range (n):
smaller[i] = s[i] < s[k - 1 ];
greater[i] = s[i] > s[k - 1 ];
# Declaring a vector to store
# difference of greater and smaller
# characters for each position
diff = [ 0 ] * n
for i in range (n):
diff[i] = smaller[i] - greater[i];
# Substrings in (0 to n)
val1 = sum ( 0 , n, diff);
# Substrings in (0 to k-1)
val2 = sum ( 0 , k - 1 , diff);
# Substrings in (k to n)
val3 = sum (k, n, diff);
# Considering only those sub strings
# with difference 0 that
# contains s[k-1]
return val1 - val2 - val3;
# Driver code S = "ecadgg" ;
K = 4 ;
# Function call print (numberOfSubstrings(S, K));
# This code is contributed by Saurabh Jaiswal
|
// C# code for the above approach using System;
using System.Collections;
using System.Collections.Generic;
public class GFG {
// Function for finding the number of
// sub strings in (start, end) where
// sum of difference is zero
public static int sum( int start, int end, int [] v)
{
// Dictionary to store number of subarrays
// starting from index zero having
// particular value of sum.
Dictionary< int , int > prevSum
= new Dictionary< int , int >();
int res = 0, currSum = 0;
for ( int i = start; i < end; i++) {
// Add current element to sum so far.
currSum += v[i];
// If currsum is equal to 0, then
// a new subarray is found.
// So increase count of subarrays.
if (currSum == 0)
res++;
if (prevSum.ContainsKey(currSum)) {
res += prevSum[currSum];
prevSum[currSum] += 1;
}
// Add currsum value to count of
// different values of sum.
else {
prevSum.Add(currSum, 1);
}
}
return res;
}
// Function to find odd length substrings
// whose median is equal to s[k-1]
public static int numberOfSubstrings(String s, int k)
{
int n = s.Length;
// Initializing vectors for storing
// element is smaller or greater
// than median
int [] smaller = new int [n];
int [] greater = new int [n];
for ( int i = 0; i < n; i++) {
smaller[i] = (s[i] < s[k - 1]) ? 1 : 0;
greater[i] = (s[i] > s[k - 1]) ? 1 : 0;
}
// Declaring a vector to store
// difference of greater and smaller
// characters for each position
int [] diff = new int [n];
for ( int i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
// Substrings in (0 to n)
int val1 = sum(0, n, diff);
// Substrings in (0 to k-1)
int val2 = sum(0, k - 1, diff);
// Substrings in (k to n)
int val3 = sum(k, n, diff);
// Considering only those sub strings
// with difference 0 that
// contains s[k-1]
return val1 - val2 - val3;
}
static public void Main()
{
// Code
String S = "ecadgg" ;
int K = 4;
// Function call
Console.Write(numberOfSubstrings(S, K));
}
} // This code is contributed by lokeshmvs21. |
<script>
// JavaScript code for the above approach
// Function for finding the number of
// sub strings in (start, end) where
// sum of difference is zero
function sum(start, end, v) {
// STL map to store number of subarrays
// starting from index zero having
// particular value of sum.
let prevSum = new Map();
let res = 0, currSum = 0;
for (let i = start; i < end; i++) {
// Add current element to sum so far.
currSum += v[i];
// If currsum is equal to 0, then
// a new subarray is found.
// So increase count of subarrays.
if (currSum == 0)
res++;
if (prevSum.has(currSum))
res += (prevSum.get(currSum));
// Add currsum value to count of
// different values of sum.
if (prevSum.has(currSum))
prevSum.set(currSum, prevSum.get(currSum) + 1);
else
prevSum.set(currSum, 1);
}
return res;
}
// Function to find odd length substrings
// whose median is equal to s[k-1]
function numberOfSubstrings(s, k) {
let n = s.length;
// Initializing vectors for storing
// element is smaller or greater
// than median
let smaller = new Array(n).fill(0), greater = new Array(n).fill(0);
for (let i = 0; i < n; i++) {
smaller[i] = s[i] < s[k - 1];
greater[i] = s[i] > s[k - 1];
}
// Declaring a vector to store
// difference of greater and smaller
// characters for each position
let diff = new Array(n).fill(0);
for (let i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
// Substrings in (0 to n)
let val1 = sum(0, n, diff);
// Substrings in (0 to k-1)
let val2 = sum(0, k - 1, diff);
// Substrings in (k to n)
let val3 = sum(k, n, diff);
// Considering only those sub strings
// with difference 0 that
// contains s[k-1]
return val1 - val2 - val3;
}
// Driver code
let S = "ecadgg" ;
let K = 4;
// Function call
document.write(numberOfSubstrings(S, K));
// This code is contributed by Potta Lokesh </script>
|
4
Time Complexity: O(N)
Auxiliary Space: O(N)