Lexicographically smallest K-length substring containing maximum number of vowels
Given string str containing only the lowercase English alphabet and an integer K, the task is to find a K length substring that contains the maximum number of vowels (i.e. ‘a’, ‘e’, ‘i’, ‘o’, ‘u’). If there are multiple such substrings, return the substring which is lexicographically smallest.
Examples:
Input: str = “geeksforgeeks”, K = 4
Output: eeks
Explanation:
The substrings with the maximum count of vowels are “geek”, “eeks” which includes 2 vowels. But “eeks” is lexicographically smallest.
Input: str = “ceebbaceeffo”, K = 3
Output: ace
Explanation:
Lexicographically, substrings with the maximum count of vowels are “ace”.
Naive Approach:
To solve the problem mentioned above, we have to generate all the substrings of length K and store the lexicographically smallest of all such substrings which contain the maximum number of vowels.
Time Complexity: O(N2)
Efficient Approach:
The above-mentioned procedure can be optimized by creating a prefix sum array pref[] of vowels where the ith index contains the count of vowels from 0 to the ith index. The count of vowels for any substring str[l : r] can be given by pref[r]-pref[l-1]. Then, find the lexicographically smallest substring with the maximum count of vowels.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
string maxVowelSubString(
string str, int K)
{
int N = str.length();
int pref[N];
for ( int i = 0; i < N; i++) {
if (str[i] == 'a'
or str[i] == 'e'
or str[i] == 'i'
or str[i] == 'o'
or str[i] == 'u' )
pref[i] = 1;
else
pref[i] = 0;
if (i)
pref[i] += pref[i - 1];
}
int maxCount = pref[K - 1];
string res = str.substr(0, K);
for ( int i = K; i < N; i++) {
int currCount
= pref[i]
- pref[i - K];
if (currCount > maxCount) {
maxCount = currCount;
res = str.substr(i - K + 1, K);
}
else if (currCount == maxCount) {
string temp
= str.substr(
i - K + 1, K);
if (temp < res)
res = temp;
}
}
return res;
}
int main()
{
string str = "ceebbaceeffo" ;
int K = 3;
cout << maxVowelSubString(str, K);
return 0;
}
|
Java
class GFG{
static String maxVowelSubString(String str,
int K)
{
int N = str.length();
int []pref = new int [N];
for ( int i = 0 ; i < N; i++)
{
if (str.charAt(i) == 'a' ||
str.charAt(i) == 'e' ||
str.charAt(i) == 'i' ||
str.charAt(i) == 'o' ||
str.charAt(i) == 'u' )
pref[i] = 1 ;
else
pref[i] = 0 ;
if (i != 0 )
pref[i] += pref[i - 1 ];
}
int maxCount = pref[K - 1 ];
String res = str.substring( 0 , K);
for ( int i = K; i < N; i++)
{
int currCount = pref[i] -
pref[i - K];
if (currCount > maxCount)
{
maxCount = currCount;
res = str.substring(i - K + 1 ,
i + 1 );
}
else if (currCount == maxCount)
{
String temp = str.substring(i - K + 1 ,
i + 1 );
if (temp.compareTo(res) < 0 )
res = temp;
}
}
return res;
}
public static void main(String []args)
{
String str = "ceebbaceeffo" ;
int K = 3 ;
System.out.print(maxVowelSubString(str, K));
}
}
|
Python3
def maxVowelSubString(str1, K):
N = len (str1)
pref = [ 0 for i in range (N)]
for i in range (N):
if (str1[i] = = 'a' or
str1[i] = = 'e' or
str1[i] = = 'i' or
str1[i] = = 'o' or
str1[i] = = 'u' ):
pref[i] = 1
else :
pref[i] = 0
if (i):
pref[i] + = pref[i - 1 ]
maxCount = pref[K - 1 ]
res = str1[ 0 :K]
for i in range (K, N):
currCount = pref[i] - pref[i - K]
if (currCount > maxCount):
maxCount = currCount
res = str1[i - K + 1 : i + 1 ]
elif (currCount = = maxCount):
temp = str1[i - K + 1 : i + 1 ]
if (temp < res):
res = temp
return res
if __name__ = = '__main__' :
str1 = "ceebbaceeffo"
K = 3
print (maxVowelSubString(str1, K))
|
C#
using System;
class GFG{
static string maxVowelSubString( string str,
int K)
{
int N = str.Length;
int []pref = new int [N];
for ( int i = 0; i < N; i++)
{
if (str[i] == 'a' ||
str[i] == 'e' ||
str[i] == 'i' ||
str[i] == 'o' ||
str[i] == 'u' )
pref[i] = 1;
else
pref[i] = 0;
if (i != 0)
pref[i] += pref[i - 1];
}
int maxCount = pref[K - 1];
string res = str.Substring(0, K);
for ( int i = K; i < N; i++)
{
int currCount = pref[i] -
pref[i - K];
if (currCount > maxCount)
{
maxCount = currCount;
res = str.Substring(i - K + 1, K);
}
else if (currCount == maxCount)
{
string temp = str.Substring(i - K + 1, K);
if ( string .Compare(temp, res) == -1)
res = temp;
}
}
return res;
}
public static void Main()
{
string str = "ceebbaceeffo" ;
int K = 3;
Console.Write(maxVowelSubString(str, K));
}
}
|
Javascript
<script>
function maxVowelSubString(str, K)
{
var N = str.length;
var pref = Array(N);
for ( var i = 0; i < N; i++) {
if (str[i] == 'a'
|| str[i] == 'e'
|| str[i] == 'i'
|| str[i] == 'o'
|| str[i] == 'u' )
pref[i] = 1;
else
pref[i] = 0;
if (i)
pref[i] += pref[i - 1];
}
var maxCount = pref[K - 1];
var res = str.substring(0, K);
for ( var i = K; i < N; i++) {
var currCount
= pref[i]
- pref[i - K];
if (currCount > maxCount) {
maxCount = currCount;
res = str.substring(i - K + 1, i - 1);
}
else if (currCount == maxCount) {
var temp
= str.substring(
i - K + 1, i + 1);
if (temp < res)
res = temp;
}
}
return res;
}
var str = "ceebbaceeffo" ;
var K = 3;
document.write( maxVowelSubString(str, K));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N), where N is the length of the given string.
Time Optimized Approach :
we are using sliding window concept by means of mapping (map stl cpp).
let’s see approach/algorithm:
- first declare a map.
- go on traversing and mapping each character.
- if i>=k then remove i-kth element in map then.
- count all vowels in substr or map.
- take max of count if count is greater then max then traverse over string (i-k)+1 to i then store substr.
C++
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
bool isVowel( char ch){
return (ch== 'a' ||ch== 'e' ||ch== 'i' ||ch== 'o' ||ch== 'u' );
}
int main() {
string s= "geeksforgeeks" ;
int k=4;
unordered_map< char , int >mp;
int maxelement=INT_MIN;
string res;
for ( int i=0;i<s.size();i++){
mp[s[i]]++;
int cnt=0;string temp= "" ;
if (i>=k){
--mp[s[i-k]];
}
for ( auto &it:mp){
if (isVowel(it.first)){
cnt+=it.second;
}
}
if (maxelement<cnt&&i>=k){
maxelement=cnt;
temp=s.substr((i-k)+1,i);
res=temp;
}
}
cout<<res<<endl;
cout<<maxelement<<endl;
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static boolean isVowel( char ch) {
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' );
}
public static void main(String[] args) {
String s = "geeksforgeeks" ;
int k = 4 ;
Map<Character, Integer> mp = new HashMap<>();
int maxElement = Integer.MIN_VALUE;
String res = "" ;
for ( int i = 0 ; i < s.length(); i++) {
mp.put(s.charAt(i), mp.getOrDefault(s.charAt(i), 0 ) + 1 );
int cnt = 0 ;
String temp = "" ;
if (i >= k) {
char removedChar = s.charAt(i - k);
mp.put(removedChar, mp.get(removedChar) - 1 );
if (mp.get(removedChar) == 0 ) {
mp.remove(removedChar);
}
}
for (Map.Entry<Character, Integer> entry : mp.entrySet()) {
if (isVowel(entry.getKey())) {
cnt += entry.getValue();
}
}
if (maxElement < cnt && i >= k) {
maxElement = cnt;
temp = s.substring(i - k + 1 , i + 1 );
res = temp;
}
}
System.out.println(res);
System.out.println(maxElement);
}
}
|
Python3
def isVowel(ch):
return ch = = 'a' or ch = = 'e' or ch = = 'i' or ch = = 'o' or ch = = 'u'
s = "geeksforgeeks"
k = 4
mp = {}
maxelement = float ( '-inf' )
res = ""
for i in range ( len (s)):
if s[i] not in mp:
mp[s[i]] = 0
mp[s[i]] + = 1
cnt = 0
temp = ""
if i > = k:
mp[s[i - k]] - = 1
if mp[s[i - k]] = = 0 :
del mp[s[i - k]]
for key in mp:
if isVowel(key):
cnt + = mp[key]
if maxelement < cnt and i > = k:
maxelement = cnt
temp = s[(i - k + 1 ):(i + 1 )]
res = temp
print (res)
print (maxelement)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static bool IsVowel( char ch)
{
return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' );
}
static void Main()
{
string s = "geeksforgeeks" ;
int k = 4;
Dictionary< char , int > mp = new Dictionary< char , int >();
int maxelement = int .MinValue;
string res = "" ;
for ( int i = 0; i < s.Length; i++)
{
if (!mp.ContainsKey(s[i]))
mp[s[i]] = 0;
mp[s[i]]++;
int cnt = 0;
string temp = "" ;
if (i >= k)
{
char toRemove = s[i - k];
mp[toRemove]--;
if (mp[toRemove] == 0)
mp.Remove(toRemove);
}
foreach ( var item in mp)
{
if (IsVowel(item.Key))
{
cnt += item.Value;
}
}
if (maxelement < cnt && i >= k)
{
maxelement = cnt;
temp = s.Substring(i - k + 1, k);
res = temp;
}
}
Console.WriteLine(res);
Console.WriteLine(maxelement);
}
}
|
Javascript
function isVowel(ch){
return (ch== 'a' ||ch== 'e' ||ch== 'i' ||ch== 'o' ||ch== 'u' );
}
let s= "geeksforgeeks" ;
let k=4;
let mp= new Map();
let maxelement=Number.MIN_VALUE;
let res= "" ;
for (let i=0;i<s.length;i++){
if (!mp.has(s[i])) {
mp.set(s[i], 0);
}
mp.set(s[i], mp.get(s[i]) + 1);
let cnt=0;
let temp= "" ;
if (i>=k){
const charToRemove = s[i - k];
mp.set(charToRemove, mp.get(charToRemove) - 1);
if (mp.get(charToRemove) === 0) {
mp. delete (charToRemove);
}
}
for (const [key, value] of mp) {
if (isVowel(key)) {
cnt += value;
}
}
if (maxelement<cnt && i>=k){
maxelement=cnt;
temp=s.substring((i-k)+1,i+1);
res=temp;
}
}
console.log(res);
console.log(maxelement);
|
Complexity Analysis:
Time Complexity : O(n*k).
Space Complexity : O(k).
Space Optimized Approach :
Instead of storing prefix sums, we can use a sliding window and update our result at each maximum.
C++
#include <iostream>
using namespace std;
bool isVowel( char c)
{
return c == 'a' or c == 'e' or c == 'i' or c == 'o'
or c == 'u' ;
}
string maxVowelSubstring(string s, int k)
{
int maxCount = 0;
string res = s.substr(
0, k);
for ( int i = 0, count = 0; i < s.size();
i++)
{
if (isVowel(
s[i]))
count++;
if (i >= k
and isVowel(
s[i - k]))
count--;
if (count > maxCount)
{
maxCount = count;
if (i >= k)
res = s.substr(i - k + 1,
k);
}
if (count == maxCount
and i >= k)
{
string t = s.substr(i - k + 1, k);
if (t < res)
res = t;
}
}
return res;
}
int main()
{
string str = "geeksforgeeks" ;
int k = 4;
cout << maxVowelSubstring(str, k);
return 0;
}
|
Java
import java.io.*;
class GFG {
static boolean isVowel( char c){
return c == 'a' || c == 'e' || c == 'i' || c == 'o'
|| c == 'u' ;
}
static String maxVowelSubString(String s, int k)
{
int maxCount = 0 ;
String res = s.substring( 0 , k);
for ( int i = 0 , count = 0 ; i < s.length();i++)
{
if (isVowel(s.charAt(i)))
count++;
if (i >= k && isVowel(s.charAt(i - k)))
count--;
if (count > maxCount)
{
maxCount = count;
if (i >= k)
res = s.substring(i - k + 1 ,i + 1 );
}
if (count == maxCount && i >= k)
{
String t = s.substring(i - k + 1 , i + 1 );
if (t.compareTo(res) < 0 ){
res = t;
}
}
}
return res;
}
public static void main (String[] args) {
String str = "geeksforgeeks" ;
int k = 4 ;
System.out.println(maxVowelSubString(str, k));
}
}
|
Python3
def isVowel(c):
return (c = = 'a' or c = = 'e' or c = = 'i' or c = = 'o' or c = = 'u' )
def maxVowelSubstring(s, k):
maxCount = 0
res = s[ 0 :k]
count = 0
for i in range ( len (s)):
if (isVowel(s[i])):
count + = 1
if (i > = k and isVowel(s[i - k])):
count - = 1
if (count > maxCount):
maxCount = count
if (i > = k):
res = s[i - k + 1 : i + 1 ]
if (count = = maxCount and i > = k):
t = s[i - k + 1 : i + 1 ]
if (t < res):
res = t
return res
str = "geeksforgeeks"
k = 4
print (maxVowelSubstring( str , k))
|
C#
using System;
class GFG
{
static bool IsVowel( char c)
{
return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ;
}
static string maxVowelSubString( string s, int k)
{
int maxCount = 0;
string res = s.Substring(0, k);
for ( int i = 0, count = 0; i < s.Length; i++)
{
if (IsVowel(s[i]))
count++;
if (i >= k && IsVowel(s[i - k]))
count--;
if (count > maxCount)
{
maxCount = count;
if (i >= k)
res = s.Substring(i - k + 1, k);
}
if (count == maxCount && i >= k)
{
string t = s.Substring(i - k + 1, k);
if ( string .Compare(t, res) < 0)
{
res = t;
}
}
}
return res;
}
static void Main( string [] args)
{
string str = "geeksforgeeks" ;
int k = 4;
Console.WriteLine(maxVowelSubString(str, k));
}
}
|
Javascript
<script>
function isVowel(c)
{
return (c == 'a' || c == 'e' || c == 'i' || c == 'o'
|| c == 'u' );
}
function maxVowelSubstring(s, k)
{
let maxCount = 0;
let res = s.substr(0, k);
for (let i = 0, count = 0; i < s.length; i++)
{
if (isVowel(s[i]))
count++;
if (i >= k && isVowel(s[i - k]))
count--;
if (count > maxCount)
{
maxCount = count;
if (i >= k)
res = s.substr(i - k + 1, k);
}
if (count == maxCount && i >= k)
{
let t = s.substr(i - k + 1, k);
if (t < res)
res = t;
}
}
return res;
}
let str = "geeksforgeeks" ;
let k = 4;
document.write(maxVowelSubstring(str, k));
</script>
|
Time Complexity: O(N)
Space Complexity: O(1)
Last Updated :
06 Oct, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...