Queries for Nth smallest character for a given range in a string
Last Updated :
14 Jun, 2021
Given a string str which consists of only lowercase letters and an array arr[][] that represents range queries on the given string str where each query contains 3 integers, {L, R, N} such that for each query we have to output the Nth smallest character in the given range [L, R] as specified in the query.
Examples:
Input: str = “afbccdeb”, arr[][] = {{2, 4, 1}, {1, 6, 4}, {1, 8, 7}}
Output: b c e
Explanation:
1st smallest character in range [2, 4] or in the sub-string “fbc” is ‘b’
4th smallest character in range [1, 6] or in the sub-string “afbccd” is ‘c’
7th smallest character in range [1, 8] or in the whole string is ‘e’
Input: str = “geeksforgeeks”, arr[][] = {{1, 4, 2}, {3, 7, 3}, {4, 13, 4}}
Output: e k g
Explanation:
2nd smallest character in range [1, 4] or in the sub-string “geek” is ‘e’
3rd smallest character in range [3, 7] or in the sub-string “eksfo” is ‘k’
4th smallest character in range [4, 13] or in the sub-string “sforgeeks”is ‘g’
Naive Approach: A naive approach is to run a loop from L to R and generate a substring in this range. Once the substring is found, sort the substring to find Nth character in the sorted string.
Time Complexity Analysis:
- In the worst case, traversing from L to R will have a complexity of O(N).
- Sorting a substring takes a complexity of O(N * Log(N)).
- Since we are sorting the substring for every query, therefore, the overall time complexity is O(N2 * Log(N)).
Efficient Approach: The idea is to make use of a two-dimensional hash table. The hash table H[][] is initialized for N rows and 26 columns where N represents the length of the string and 26 as there are a total of 26 lowercase letters.
The idea behind hashtable is that for each index i where ‘i’ ranges from 1 to N, we keep a track of the number of occurrence of each of the 26 lowercase letters on or before the ith index. To do this, hashing is used where each character is treated as a number in the following way:
'a' -> 0
'b' -> 1
.
.
.
'z' -> 25
Therefore, for each query {L, R, N}, we get the occurrence of each character for the given range by subtracting the elements of H[L – 1][j] from H[R][j] where j ranges from 0 to 25 in the form of a hash table. After this, all we need to do is traverse from 0 to 25 and add the contents of the resultant array. Whenever the sum is equal to or exceeds N, the character representing that index is the required answer.
For example, if on 5th index(j = 4), the sum till then exceeds N, the answer becomes ‘e’ as 4 is equivalent to the character ‘e’. Below is the pictorial representation of the sample case:

The image describes the hashtable corresponding to the given string. For range [2, 4], we perform subtraction of the contents from H[2 – 1] from H[4]. We get:

Clearly this resultant array contains the count of elements that are within the range [2, 4]. So we simply traverse from 0 to 25 and count the contents until we reach N. In the query for N = 1 the answer is ‘b’, for N = 2 the answer becomes ‘c’ and so on.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
struct Query {
int l, r, n;
};
int findSmallest(string s, Query q[], int m)
{
int N = s.length();
int H[N + 1][26];
memset (H, 0, sizeof (H));
for ( int i = 1; i <= N; i++) {
++H[i][s[i - 1] - 'a' ];
for ( int j = 0; j < 26; j++) {
H[i][j] += H[i - 1][j];
}
}
for ( int j = 0; j < m; j++) {
int l = q[j].l, r = q[j].r,
n = q[j].n;
int sum = 0;
for ( int i = 0; i < 26; i++) {
sum += H[r][i] - H[l - 1][i];
if (sum >= n) {
cout << ( char )( 'a' + i) << "\n" ;
break ;
}
}
}
}
int main()
{
string s = "afbccdeb" ;
Query q[] = { { 2, 4, 1 },
{ 1, 6, 4 },
{ 1, 8, 7 } };
int x = sizeof (q) / sizeof (q[0]);
findSmallest(s, q, x);
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static class Query {
public int l, r, n;
public Query( int l, int r, int n)
{
this .l = l;
this .r = r;
this .n = n;
}
}
public static void printSmallest(String s, Query[] q)
{
int N = s.length();
int [][] H = new int [N + 1 ][ 26 ];
for ( int i = 1 ; i <= N; i++) {
++H[i][s.charAt(i - 1 ) - 'a' ];
for ( int j = 0 ; j < 26 ; j++) {
H[i][j] += H[i - 1 ][j];
}
}
int m = q.length;
for ( int j = 0 ; j < m; j++) {
int l = q[j].l, r = q[j].r,
n = q[j].n;
int sum = 0 ;
for ( int i = 0 ; i < 26 ; i++) {
sum += H[r][i] - H[l - 1 ][i];
if (sum >= n) {
System.out.println(( char )( 'a' + i));
break ;
}
}
}
}
public static void main(String args[])
{
String s = "afbccdeb" ;
Query[] q = { new Query( 2 , 4 , 1 ),
new Query( 1 , 6 , 4 ),
new Query( 1 , 8 , 7 ) };
printSmallest(s, q);
}
}
|
Python3
def findSmallest(s, q, m):
N = len (s)
H = [[ 0 for i in range ( 26 )] for i in range (N + 1 )]
for i in range ( 1 , N + 1 ):
H[i][ ord (s[i - 1 ]) - ord ( 'a' )] + = 1
for j in range ( 26 ):
H[i][j] + = H[i - 1 ][j]
for j in range (m):
l = q[j][ 0 ]
r = q[j][ 1 ]
n = q[j][ 2 ]
sum = 0
for i in range ( 26 ):
sum + = H[r][i] - H[l - 1 ][i]
if ( sum > = n):
print ( chr ( ord ( 'a' ) + i))
break
if __name__ = = '__main__' :
s = "afbccdeb"
q = [ [ 2 , 4 , 1 ],
[ 1 , 6 , 4 ],
[ 1 , 8 , 7 ] ]
x = len (q)
findSmallest(s, q, x)
|
C#
using System;
class GFG {
public class Query {
public int l, r, n;
public Query( int l, int r, int n)
{
this .l = l;
this .r = r;
this .n = n;
}
}
public static void printSmallest(String s, Query[] q)
{
int N = s.Length;
int [,] H = new int [N + 1,26];
for ( int i = 1; i <= N; i++) {
++H[i, s[i - 1] - 'a' ];
for ( int j = 0; j < 26; j++) {
H[i, j] += H[i - 1, j];
}
}
int m = q.Length;
for ( int j = 0; j < m; j++) {
int l = q[j].l, r = q[j].r,
n = q[j].n;
int sum = 0;
for ( int i = 0; i < 26; i++) {
sum += H[r, i] - H[l - 1, i];
if (sum >= n) {
Console.WriteLine(( char )( 'a' + i));
break ;
}
}
}
}
public static void Main(String []args)
{
String s = "afbccdeb" ;
Query[] q = { new Query(2, 4, 1),
new Query(1, 6, 4),
new Query(1, 8, 7) };
printSmallest(s, q);
}
}
|
Javascript
<script>
class Query
{
constructor(l,r,n)
{
this .l = l;
this .r = r;
this .n = n;
}
}
function printSmallest(s,q)
{
let N = s.length;
let H = new Array(N + 1);
for (let i = 0; i < N + 1; i++)
{
H[i] = new Array(26);
for (let j = 0; j < 26; j++)
{
H[i][j] = 0;
}
}
for (let i = 1; i <N; i++)
{
++H[i][s[i].charCodeAt(0) - 'a' .charCodeAt(0)];
for (let j = 0; j < 26; j++) {
H[i][j] += H[i - 1][j];
}
}
let m = q.length;
for (let j = 0; j < m; j++) {
let l = q[j].l, r = q[j].r,
n = q[j].n;
let sum = 0;
for (let i = 0; i < 26; i++) {
sum += H[r][i] - H[l - 1][i];
if (sum >= n) {
document.write(String.fromCharCode( 'a' .charCodeAt(0) + i)+ "<br>" );
break ;
}
}
}
}
let s = "afbccdeb" ;
let q = [ new Query(2, 4, 1),
new Query(1, 6, 4),
new Query(1, 8, 7) ];
printSmallest(s, q);
</script>
|
Time Complexity Analysis:
- For the above approach, though the preprocessing consists of two loops, the second loop runs for a constant number of times(26). Therefore, the time taken for preprocessing is O(N).
- After preprocessing, for every query, the character is returned in constant time as again here the for loop runs a constant number of times(26). Therefore, the time taken for answering each query is O(1).
Similar Reads
Queries to find first occurrence of a character in a given range
Given a string S of length N and an array Q[][] of dimension M Ã 3 consisting of queries of type {L, R, C}, the task is to print the first index of the character C in the range [L, R], if found. Otherwise, print -1. Examples: Input: S= "abcabcabc", Q[][] = { { 0, 3, 'a' }, { 0, 2, 'b' }, { 2, 4, 'z'
9 min read
Lexicographically smallest anagram of given string in range [L, R] for Q queries
Given a string S of size N and an array queries, containing Q queries in the form of L, R. The task is to find the lexicographically smallest anagram of string from L to R for each query. Example: Input: S = "bbaacd"queries[]={{1, 3}, {2, 5}}Output:aabaacd Input: S="bbdfaaacaed"queries[]={{0, 4}, {4
7 min read
Find last index of a character in a string
Given a string str and a character x, find last index of x in str. Examples : Input : str = "geeks", x = 'e' Output : 2 Last index of 'e' in "geeks" is: 2 Input : str = "Hello world!", x = 'o' Output : 7 Last index of 'o' is: 7 Recommended PracticeLast index of a character in the stringTry It! Metho
8 min read
Find the Nth occurrence of a character in the given String
Given string str, a character ch, and a value N, the task is to find the index of the Nth occurrence of the given character in the given string. Print -1 if no such occurrence exists. Examples: Input: str = "Geeks", ch = 'e', N = 2 Output: 2 Input: str = "GFG", ch = 'e', N = 2 Output: -1 Recommended
7 min read
Minimum jumps from either end to reach largest and smallest character in given String
Given a string str, the task is to find the minimum number of moves required to reach lexicographically largest and smallest characters. In one move, a jump can be made from leftmost side or the rightmost side of given string. Examples: Input: str = AEDCB, N = 5 Output: 2Explanation: take two steps
6 min read
Longest Substring of given characters by replacing at most K characters for Q queries
Given a string s of length N, and Q queries, each of type (K, C) where K is an integer C is a character, the task is to replace at most K characters of the string by C and have to print the maximum length of possible substring containing only character C. Examples : Input: s = "yamatonadeshiko", N =
12 min read
Queries to find kth greatest character in a range with updates (Easy Task)
Given a string str of length N, and Q queries of the following two types: (1 L R K): Find the Kth greatest character (non-distinct) from the range of indices [L, R] (1-based indexing)(2 J C): Replace the Jth character from the string by character C.Examples: Input: str = "abcddef", Q = 3, queries[][
15+ min read
Frequency of lexicographically Kth smallest character in the a string
Given a string S of length N and an integer K, the task is to find the frequency of the lexicographically Kth smallest character present in the given string. Examples: Input: S = "geeksforgeeks", K = 3Output: 4Explanation: The lexicographically 3rd smallest character in S is 'e'. Frequency of 'e' in
5 min read
Lexicographically smallest string formed by removing at most one character
Given a string s, the task is to find the lexicographically smallest string that can be formed by removing at most one character from the given string. Examples: Input: s = "abcda" Output: "abca"Explanation: One can remove 'd' to get "abca" which is the lexicographically smallest string possible. In
4 min read
Smallest alphabet greater than a given character
Given a list of sorted characters consisting of both Uppercase and Lowercase Alphabets and a particular target value, say K, the task is to find the smallest element in the list that is larger than K. Letters also wrap around. For example, if K = 'z' and letters = ['A', 'r', 'z'], then the answer wo
10 min read