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.
- 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++
#include <bits/stdc++.h>
using namespace std;
int sum( int start, int end, vector< int >& v)
{
unordered_map< int , int > prevSum;
int res = 0, currSum = 0;
for ( int i = start; i < end; i++) {
currSum += v[i];
if (currSum == 0)
res++;
if (prevSum.find(currSum) != prevSum.end())
res += (prevSum[currSum]);
prevSum[currSum]++;
}
return res;
}
int numberOfSubstrings(string& s, int k)
{
int n = s.size();
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];
}
vector< int > diff(n, 0);
for ( int i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
int val1 = sum(0, n, diff);
int val2 = sum(0, k - 1, diff);
int val3 = sum(k, n, diff);
return val1 - val2 - val3;
}
int main()
{
string S = "ecadgg" ;
int K = 4;
cout << numberOfSubstrings(S, K);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int sum( int start, int end, int v[])
{
HashMap<Integer, Integer> prevSum
= new HashMap<Integer, Integer>();
int res = 0 , currSum = 0 ;
for ( int i = start; i < end; i++) {
currSum += v[i];
if (currSum == 0 )
res++;
if (prevSum.containsKey(currSum)) {
res += prevSum.get(currSum);
prevSum.put(currSum,
prevSum.get(currSum) + 1 );
}
prevSum.put(currSum, 1 );
}
return res;
}
public static int numberOfSubstrings(String s, int k)
{
int n = s.length();
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 ;
}
int diff[] = new int [n];
for ( int i = 0 ; i < n; i++)
diff[i] = smaller[i] - greater[i];
int val1 = sum( 0 , n, diff);
int val2 = sum( 0 , k - 1 , diff);
int val3 = sum(k, n, diff);
return val1 - val2 - val3;
}
public static void main(String[] args)
{
String S = "ecadgg" ;
int K = 4 ;
System.out.print(numberOfSubstrings(S, K));
}
}
|
Python3
def sum (start, end, v):
prevSum = {};
res = 0
currSum = 0 ;
for i in range (start, end):
currSum + = v[i];
if (currSum = = 0 ):
res + = 1
if (currSum in prevSum):
res + = (prevSum[currSum]);
if (currSum in prevSum):
prevSum[currSum] + = 1
else :
prevSum[currSum] = 1
return res;
def numberOfSubstrings(s, k):
n = len (s)
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 ];
diff = [ 0 ] * n
for i in range (n):
diff[i] = smaller[i] - greater[i];
val1 = sum ( 0 , n, diff);
val2 = sum ( 0 , k - 1 , diff);
val3 = sum (k, n, diff);
return val1 - val2 - val3;
S = "ecadgg" ;
K = 4 ;
print (numberOfSubstrings(S, K));
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
public class GFG {
public static int sum( int start, int end, int [] v)
{
Dictionary< int , int > prevSum
= new Dictionary< int , int >();
int res = 0, currSum = 0;
for ( int i = start; i < end; i++) {
currSum += v[i];
if (currSum == 0)
res++;
if (prevSum.ContainsKey(currSum)) {
res += prevSum[currSum];
prevSum[currSum] += 1;
}
else {
prevSum.Add(currSum, 1);
}
}
return res;
}
public static int numberOfSubstrings(String s, int k)
{
int n = s.Length;
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;
}
int [] diff = new int [n];
for ( int i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
int val1 = sum(0, n, diff);
int val2 = sum(0, k - 1, diff);
int val3 = sum(k, n, diff);
return val1 - val2 - val3;
}
static public void Main()
{
String S = "ecadgg" ;
int K = 4;
Console.Write(numberOfSubstrings(S, K));
}
}
|
Javascript
<script>
function sum(start, end, v) {
let prevSum = new Map();
let res = 0, currSum = 0;
for (let i = start; i < end; i++) {
currSum += v[i];
if (currSum == 0)
res++;
if (prevSum.has(currSum))
res += (prevSum.get(currSum));
if (prevSum.has(currSum))
prevSum.set(currSum, prevSum.get(currSum) + 1);
else
prevSum.set(currSum, 1);
}
return res;
}
function numberOfSubstrings(s, k) {
let n = s.length;
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];
}
let diff = new Array(n).fill(0);
for (let i = 0; i < n; i++)
diff[i] = smaller[i] - greater[i];
let val1 = sum(0, n, diff);
let val2 = sum(0, k - 1, diff);
let val3 = sum(k, n, diff);
return val1 - val2 - val3;
}
let S = "ecadgg" ;
let K = 4;
document.write(numberOfSubstrings(S, K));
</script>
|
Time Complexity: O(N) Auxiliary Space: O(N)
|