Queries to find Kth greatest character in a range [L, R] from a string with updates

Given a string str of length N, and Q queries of the following two types:

  1. (1 L R K): Find the Kth greatest character (non-distinct) from the range of indices [L, R] (1-based indexing)
  2. (2 J C): Replace the Jth character from the string by character C.

Examples:

Input: str = “abcddef”, Q = 3, queries[][] = {{1, 2, 5, 3}, {2, 4, g}, {1, 1, 4, 3}}
Output:
c

Explanation : 
Query 1: String between indices (2, 5) is “bcdd”. The third largest character is ‘c’. Therefore, c is the required output. 
Query 2: Replace S[4] by ‘g’. Therefore, S modifies to “abcgdef”. 
Query 3: String between indices (1, 4) is “abcg”. The third largest character is ‘b’. Therefore, b is the required output.

Input: str=” afcdehgk”, Q = 4, queries[][] = {{1, 2, 5, 4}, {2, 5, m}, {1, 3, 7, 2}, {1, 1, 6, 4}}
Output:
c
h
d

Naive Approach: The simplest approach to solve the problem is as follows:



  • For each query of type ( 1 L R K ), find the substring of S from the range of indices [L, R], and sort this substring in non-increasing order. Print the character at the Kth index in the substring.
  • For each query of type ( 2 J C ), replace the Jth character in S by C.

Time Complexity: O ( Q * ( N log(N) ) ), where N logN is the computational complexity of sorting each substring.
Auxiliary Space: O(N)

The below code is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to implement
// the above approach
 
#include "bits/stdc++.h"
using namespace std;
 
// Function to find the kth greatest
// character from the strijng
char find_kth_largest(string str, int k)
{
 
    // Sorting the string in
    // non-increasing Order
    sort(str.begin(), str.end(),
         greater<char>());
    return str[k - 1];
}
 
// Function to print the K-th character
// from the substring S[l] .. S[r]
char printCharacter(string str, int l,
                    int r, int k)
{
    // 0-based indexing
    l = l - 1;
    r = r - 1;
 
    // Substring of str from the
    // indices l to r.
    string temp
        = str.substr(l, r - l + 1);
 
    // Extract kth Largest character
    char ans
        = find_kth_largest(temp, k);
 
    return ans;
}
 
// Function to replace character at
// pos of str by the character s
void updateString(string str, int pos,
                  char s)
{
    // Index of S to be updated.
    int index = pos - 1;
    char c = s;
 
    // Character to be replaced
    // at index in S
    str[index] = c;
}
 
// Driver Code
int main()
{
    // Given string
    string str = "abcddef";
 
    // Count of queries
    int Q = 3;
 
    // Queries
    cout << printCharacter(str, 1, 2, 2)
         << endl;
    updateString(str, 4, 'g');
    cout << printCharacter(str, 1, 5, 4)
         << endl;
 
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java Program to implement
// the above approach
//include "bits/stdJava.h"
import java.util.*;
class GFG{
 
// Function to find the kth greatest
// character from the strijng
static char find_kth_largest(char []str,
                             int k)
{
  // Sorting the String in
  // non-increasing Order
  Arrays.sort(str);
  reverse(str);
  return str[k - 1];
}
  static char[] reverse(char a[])
  {
    int i, n = a.length;
    char t;
    for (i = 0; i < n / 2; i++)
    {
      t = a[i];
      a[i] = a[n - i - 1];
      a[n - i - 1] = t;
    }
    return a;
}
   
// Function to print the K-th character
// from the subString S[l] .. S[r]
static char printCharacter(String str, int l,
                           int r, int k)
{
  // 0-based indexing
  l = l - 1;
  r = r - 1;
 
  // SubString of str from the
  // indices l to r.
  String temp = str.substring(l, r - l + 1);
 
  // Extract kth Largest character
  char ans =
    find_kth_largest(temp.toCharArray(), k);
 
  return ans;
}
 
// Function to replace character at
// pos of str by the character s
static void updateString(char []str,
                         int pos, char s)
{
  // Index of S to be updated.
  int index = pos - 1;
  char c = s;
 
  // Character to be replaced
  // at index in S
  str[index] = c;
}
 
// Driver Code
public static void main(String[] args)
{
  // Given String
  String str = "abcddef";
 
  // Count of queries
  int Q = 3;
 
  // Queries
  System.out.print(printCharacter(str, 1,
                                  2, 2) + "\n");
  updateString(str.toCharArray(), 4, 'g');
  System.out.print(printCharacter(str, 1,
                                  5, 4) + "\n");
}
}
 
// This code is contributed by shikhasingrajput

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 Program to implement
# the above approach
# Function to find the kth greatest
# character from the strrijng
def find_kth_largest(strr, k):
 
    # Sorting the in
    # non-increasing Order
    strr = sorted(strr)
    strr = strr[:: -1]
    return strr[k - 1]
 
# Function to prthe K-th character
# from the subS[l] .. S[r]
def printCharacter(strr, l, r, k):
   
    #0-based indexing
    l = l - 1
    r = r - 1
 
    # Subof strr from the
    # indices l to r.
    temp= strr[l: r - l + 1]
 
    #Extract kth Largest character
    ans = find_kth_largest(temp, k)
 
    return ans
 
# Function to replace character at
# pos of strr by the character s
def updateString(strr, pos, s):
    # Index of S to be updated.
    index = pos - 1
    c = s
 
    # Character to be replaced
    # at index in S
    strr[index] = c
 
# Driver Code
if __name__ == '__main__':
   
    # Given strring
    strr = "abcddef"
    strr=[i for i in strr]
 
    # Count of queries
    Q = 3
 
    # Queries
    print(printCharacter(strr, 1, 2, 2))
    updateString(strr, 4, 'g')
    print(printCharacter(strr, 1, 5, 4))
 
# This code is contributed by Mohit Kumar 29

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to find the kth greatest
// character from the strijng
static char find_kth_largest(char []str,
                             int k)
{
     
    // Sorting the String in
    // non-increasing Order
    Array.Sort(str);
    reverse(str);
     
    return str[k - 1];
}
 
static char[] reverse(char []a)
{
    int i, n = a.Length;
    char t;
     
    for(i = 0; i < n / 2; i++)
    {
        t = a[i];
        a[i] = a[n - i - 1];
        a[n - i - 1] = t;
    }
    return a;
}
 
// Function to print the K-th character
// from the subString S[l] .. S[r]
static char printchar(String str, int l,
                           int r, int k)
{
     
    // 0-based indexing
    l = l - 1;
    r = r - 1;
 
    // SubString of str from the
    // indices l to r.
    String temp = str.Substring(l, r - l + 1);
 
    // Extract kth Largest character
    char ans = find_kth_largest(
               temp.ToCharArray(), k);
 
    return ans;
}
 
// Function to replace character at
// pos of str by the character s
static void updateString(char []str,
                         int pos, char s)
{
     
    // Index of S to be updated.
    int index = pos - 1;
    char c = s;
 
    // char to be replaced
    // at index in S
    str[index] = c;
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Given String
    String str = "abcddef";
 
    // Count of queries
    //int Q = 3;
 
    // Queries
    Console.Write(printchar(str, 1, 2, 2) + "\n");
    updateString(str.ToCharArray(), 4, 'g');
     
    Console.Write(printchar(str, 1, 5, 4) + "\n");
}
}
 
// This code is contributed by Amit Katiyar

chevron_right


Output: 

a
b







Efficient Approach: The above approach can be optimized by precomputing the count of all the characters which are greater than or equal to character C ( ‘a’ ≤ C ≤ ‘z’ ) efficiently using a Fenwick Tree.
Follow the steps below to solve the problem:

  • Create a Fenwick Tree to store the frequencies of all characters from ‘a’ to ‘z
  • For every query of type 1, check for each character from ‘z’ to ‘a’, whether it is the Kth the greatest character.
  • In order to perform this, traverse from ‘z’ to ‘a’ and for each character, check if the count of all the characters traversed becomes ≥ K or not. Print the character for which the count becomes ≥ K.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to implement
// the above approach
 
#include "bits/stdc++.h"
using namespace std;
 
// Maximum Size of a String
const int maxn = 100005;
 
// Fenwick Tree to store the
// frequencies of 26 alphabets
int BITree[26][maxn];
 
// Size of the String.
int N;
 
// Function to update Fenwick Tree for
// Character c at index val
void update_BITree(int index, char C,
                   int val)
{
    while (index <= N) {
 
        // Add val to current node
        // Fenwick Tree
        BITree[C - 'a'][index]
            += val;
 
        // Move index to parent node
        // in update View
        index += (index & -index);
    }
}
 
// Function to get sum of frequencies
// of character c till index
int sum_BITree(int index, char C)
{
 
    // Stores the sum
    int s = 0;
    while (index) {
 
        // Add current element of
        // Fenwick tree to sum
        s += BITree[C - 'a'][index];
 
        // Move index to parent node
        // in getSum View
        index -= (index & -index);
    }
    return s;
}
 
// Function to create the Fenwick tree
void buildTree(string str)
{
    for (int i = 1; i <= N; i++) {
 
        update_BITree(i, str[i], 1);
    }
    cout << endl;
}
 
// Function to print the kth largest
// character in the range of l to r
char printCharacter(string str, int l,
                    int r, int k)
{
 
    // Stores the count of
    // charcters
    int count = 0;
 
    // Stores the required
    // character
    char ans;
 
    for (char C = 'z'; C >= 'a'; C--) {
 
        // Calculate frequency of
        // C in the given range
        int times = sum_BITree(r, C)
                    - sum_BITree(l - 1, C);
 
        // Increase count
        count += times;
 
        // If count exceeds K
        if (count >= k) {
 
            // Required character
            // found
            ans = C;
            break;
        }
    }
 
    return ans;
}
 
// Function to update character
// at pos by character s
void updateTree(string str, int pos,
                char s)
{
 
    // 0 based index system
    int index = pos;
    update_BITree(index, str[index], -1);
 
    str[index] = s;
    update_BITree(index, s, 1);
}
 
// Driver Code
int main()
{
    string str = "abcddef";
    N = str.size();
 
    // Makes the string 1-based indexed
    str = '#' + str;
 
    // Number of queries
    int Q = 3;
 
    // Construct the Fenwick Tree
    buildTree(str);
 
    cout << printCharacter(str, 1, 2, 2)
         << endl;
    updateTree(str, 4, 'g');
    cout << printCharacter(str, 1, 5, 4)
         << endl;
 
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java Program to implement
// the above approach
 
//include "bits/stdJava.h"
import java.util.*;
class GFG{
 
// Maximum Size of a String
static int maxn = 100005;
 
// Fenwick Tree to store the
// frequencies of 26 alphabets
static int [][]BITree = new int[26][maxn];
 
// Size of the String.
static int N;
 
// Function to update Fenwick Tree for
// Character c at index val
static void update_BITree(int index,
                          char C, int val)
{
  while (index <= N)
  {
    // Add val to current node
    // Fenwick Tree
    BITree[C - 'a'][index] += val;
 
    // Move index to parent node
    // in update View
    index += (index & -index);
  }
}
 
// Function to get sum of frequencies
// of character c till index
static int sum_BITree(int index, char C)
{
 
  // Stores the sum
  int s = 0;
  while (index > 0)
  {
    // Add current element of
    // Fenwick tree to sum
    s += BITree[C - 'a'][index];
 
    // Move index to parent node
    // in getSum View
    index -= (index & -index);
  }
  return s;
}
 
// Function to create the Fenwick tree
static void buildTree(String str)
{
  for (int i = 1; i <= N; i++)
  {
    update_BITree(i, str.charAt(i), 1);
  }
  System.out.println();
}
 
// Function to print the kth largest
// character in the range of l to r
static char printCharacter(String str, int l,
                           int r, int k)
{
  // Stores the count of
  // charcters
  int count = 0;
 
  // Stores the required
  // character
  char ans = 0;
 
  for (char C = 'z'; C >= 'a'; C--)
  {
    // Calculate frequency of
    // C in the given range
    int times = sum_BITree(r, C) -
      sum_BITree(l - 1, C);
 
    // Increase count
    count += times;
 
    // If count exceeds K
    if (count >= k)
    {
      // Required character
      // found
      ans = C;
      break;
    }
  }
  return ans;
}
 
// Function to update character
// at pos by character s
static void updateTree(String str,
                       int pos, char s)
{
    // 0 based index system
    int index = pos;
    update_BITree(index,
                  str.charAt(index), -1);
    str = str.substring(0, index) + s +
          str.substring(index + 1);
    update_BITree(index, s, 1);
}
 
// Driver Code
public static void main(String[] args)
{
  String str = "abcddef";
  N = str.length();
 
  // Makes the String 1-based indexed
  str = '/' + str;
 
  // Number of queries
  int Q = 3;
 
  // Conthe Fenwick Tree
  buildTree(str);
 
  System.out.print(printCharacter(str, 1,
                                  2, 2) + "\n");
  updateTree(str, 4, 'g');
  System.out.print(printCharacter(str, 1,
                                  5, 4) + "\n");
 
}
}
 
// This code is contributed by shikhasingrajput

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# Program to implement
// the above approach
using System;
class GFG{
 
// Maximum Size of a String
static int maxn = 100005;
 
// Fenwick Tree to store the
// frequencies of 26 alphabets
static int [,]BITree = new int[26, maxn];
 
// Size of the String.
static int N;
 
// Function to update Fenwick Tree for
// char c at index val
static void update_BITree(int index,
                          char C, int val)
{
  while (index <= N)
  {
    // Add val to current node
    // Fenwick Tree
    BITree[C - 'a', index] += val;
 
    // Move index to parent node
    // in update View
    index += (index & -index);
  }
}
 
// Function to get sum of frequencies
// of character c till index
static int sum_BITree(int index, char C)
{
  // Stores the sum
  int s = 0;
  while (index > 0)
  {
    // Add current element of
    // Fenwick tree to sum
    s += BITree[C - 'a', index];
 
    // Move index to parent node
    // in getSum View
    index -= (index & -index);
  }
  return s;
}
 
// Function to create the Fenwick tree
static void buildTree(String str)
{
  for (int i = 1; i <= N; i++)
  {
    update_BITree(i, str[i], 1);
  }
  Console.WriteLine();
}
 
// Function to print the kth largest
// character in the range of l to r
static char printchar(String str, int l,
                      int r, int k)
{
  // Stores the count of
  // charcters
  int count = 0;
 
  // Stores the required
  // character
  char ans = (char)0;
 
  for (char C = 'z'; C >= 'a'; C--)
  {
    // Calculate frequency of
    // C in the given range
    int times = sum_BITree(r, C) -
                sum_BITree(l - 1, C);
 
    // Increase count
    count += times;
 
    // If count exceeds K
    if (count >= k)
    {
      // Required character
      // found
      ans = C;
      break;
    }
  }
  return ans;
}
 
// Function to update character
// at pos by character s
static void updateTree(String str,
                       int pos, char s)
{
  // 0 based index system
  int index = pos;
  update_BITree(index,
                str[index], -1);
  str = str.Substring(0, index) + s +
    str.Substring(index + 1);
  update_BITree(index, s, 1);
}
 
// Driver Code
public static void Main(String[] args)
{
  String str = "abcddef";
  N = str.Length;
 
  // Makes the String 1-based indexed
  str = '/' + str;
 
  // Number of queries
  int Q = 3;
 
  // Conthe Fenwick Tree
  buildTree(str);
 
  Console.Write(printchar(str, 1, 2, 2) + "\n");
  updateTree(str, 4, 'g');
  Console.Write(printchar(str, 1, 5, 4) + "\n");
}
}
 
// This code is contributed by Rajput-Ji

chevron_right


Output: 

a
b







Time Complexity: O( QlogN + NlogN ) 
Auxiliary Space: O(26 * maxn), where maxn denotes the maximum possible length of the string.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.