Related Articles
Queries to calculate difference between the frequencies of the most and least occurring characters in specified substring
• Difficulty Level : Hard
• Last Updated : 10 Feb, 2021

Given a string str consisting of N lowercase characters and an array Q[][] with each row of the form {l, r} representing a query. For each query, the task is to find the difference between the maximum frequency and minimum frequency of the characters in the substring {str[l], …. str[r]}

Note: Consider 1 – based indexing.

Examples:

Input: N = 7, S = “abaabac”, Q[][] = {{ 2, 6 }, { 1, 7 }}
Output: 1 3
Explanation:
Query 1: ‘a’ occurs maximum number of times in the given range i.e., 3 and ‘b’ occurs minimum number of times in the given range i.e. 2. Therefore, output = 3 – 2 = 1.
Query 2: ‘a’ occurs maximum number of times in the given range i.e. 4 and ‘c’ occurs minimum number of times in the given range i.e. 1. Therefore, output = 4 – 1 = 3.

Input: N = 6, S = “aabbcc”, Q[][] = {{1, 4}, {1, 6}}
Output: 0 0
Explanation:
Query 1: ‘a’ and ‘b’ both occurs same number of times in the given range. Therefore, the output is 0.
Query 2: All ‘a’, ‘b’ and ‘c’ occurs same number of times in the given range. Therefore, the output is 0.

Naive Approach: For each query, find the frequencies of all characters in the given range, and take the difference between the maximum and minimum frequencies.

Time Complexity: O((N + 26)* |Q|)
Auxiliary Space: O(26)

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Funciton to find difference between maximum and``// minimum frequency of a character in given range``void` `maxDiffFreq(vector > queries,``                 ``string S)``{` `    ``// Stores length of string``    ``int` `N = S.size();` `    ``// Stores count of queries``    ``int` `Q = queries.size();` `    ``// Iterate over the characters``    ``// of the string``    ``for` `(``int` `i = 0; i < Q; ++i) {` `        ``// Stores l-value of a query``        ``int` `l = queries[i].first - 1;` `        ``// Stores r-value of a query``        ``int` `r = queries[i].second - 1;``        ``int` `freq = { 0 };` `        ``// Store count of every character``        ``// laying in range [l, r]``        ``for` `(``int` `j = l; j <= r; j++) {` `            ``// Update frequency of``            ``// current character``            ``freq[S[j] - ``'a'``]++;``        ``}` `        ``// Stores maximum frequency``        ``// of characters in given range``        ``int` `mx = 0;` `        ``// Stores minimum frequency``        ``// of characters in given range``        ``int` `mn = 99999999;` `        ``// Iterate over all possible characters``        ``// of the given string``        ``for` `(``int` `j = 0; j < 26; j++) {` `            ``// Update mx``            ``mx = max(mx, freq[j]);` `            ``// If (j + 'a') is present``            ``if` `(freq[j])``                ``mn = min(mn, freq[j]);``        ``}` `        ``// difference between max and min``        ``cout << mx - mn << endl;``    ``}``}` `// Driver Code``int` `main()``{` `    ``// Given string``    ``string S = ``"abaabac"``;` `    ``// Given queries``    ``vector > queries{ { 2, 6 }, { 1, 7 } };` `    ``// Function Call``    ``maxDiffFreq(queries, S);``}`

## Java

 `// Java program for the above approach``import` `java.util.*;``class` `GFG{` `  ``// Funciton to find difference between maximum and``  ``// minimum frequency of a character in given range``  ``static` `void` `maxDiffFreq(``int` `[][]queries,``                          ``String S)``  ``{` `    ``// Stores length of String``    ``int` `N = S.length();` `    ``// Stores count of queries``    ``int` `Q = queries.length;` `    ``// Iterate over the characters``    ``// of the String``    ``for` `(``int` `i = ``0``; i < Q; ++i)    ``    ``{` `      ``// Stores l-value of a query``      ``int` `l = queries[i][``0``] - ``1``;` `      ``// Stores r-value of a query``      ``int` `r = queries[i][``1``] - ``1``;``      ``int` `freq[] = ``new` `int``[``26``];` `      ``// Store count of every character``      ``// laying in range [l, r]``      ``for` `(``int` `j = l; j <= r; j++) {` `        ``// Update frequency of``        ``// current character``        ``freq[S.charAt(j) - ``'a'``]++;``      ``}` `      ``// Stores maximum frequency``      ``// of characters in given range``      ``int` `mx = ``0``;` `      ``// Stores minimum frequency``      ``// of characters in given range``      ``int` `mn = ``99999999``;` `      ``// Iterate over all possible characters``      ``// of the given String``      ``for` `(``int` `j = ``0``; j < ``26``; j++) {` `        ``// Update mx``        ``mx = Math.max(mx, freq[j]);` `        ``// If (j + 'a') is present``        ``if` `(freq[j]>``0``)``          ``mn = Math.min(mn, freq[j]);``      ``}` `      ``// difference between max and min``      ``System.out.print(mx - mn +``"\n"``);``    ``}``  ``}` `  ``// Driver Code``  ``public` `static` `void` `main(String[] args)``  ``{` `    ``// Given String``    ``String S = ``"abaabac"``;` `    ``// Given queries``    ``int` `[][]queries = { { ``2``, ``6` `}, { ``1``, ``7` `} };` `    ``// Function Call``    ``maxDiffFreq(queries, S);``  ``}``}``// This code is contributed by 29AjayKumar`

## Python3

 `# Python 3 program for the above approach` `# Funciton to find difference between maximum``# and minimum frequency of a character in``# given range``def` `maxDiffFreq(queries, S):` `    ``# Stores length of string``    ``N ``=` `len``(S)` `    ``# Stores count of queries``    ``Q ``=` `len``(queries)` `    ``# Iterate over the characters``    ``# of the string``    ``for` `i ``in` `range``(Q):` `        ``# Stores l-value of a query``        ``l ``=` `queries[i][``0``] ``-` `1` `        ``# Stores r-value of a query``        ``r ``=` `queries[i][``1``] ``-` `1``        ``freq ``=` `[``0``] ``*` `26` `        ``# Store count of every character``        ``# laying in range [l, r]``        ``for` `j ``in` `range``(l, r ``+` `1``):` `            ``# Update frequency of``            ``# current character``            ``freq[``ord``(S[j]) ``-` `ord``(``'a'``)] ``+``=` `1` `        ``# Stores maximum frequency``        ``# of characters in given range``        ``mx ``=` `0` `        ``# Stores minimum frequency``        ``# of characters in given range``        ``mn ``=` `99999999` `        ``# Iterate over all possible characters``        ``# of the given string``        ``for` `j ``in` `range``(``26``):` `            ``# Update mx``            ``mx ``=` `max``(mx, freq[j])` `            ``# If (j + 'a') is present``            ``if` `(freq[j]):``                ``mn ``=` `min``(mn, freq[j])` `        ``# Difference between max and min``        ``print``(mx ``-` `mn)` `# Driver Code``if` `__name__ ``=``=` `"__main__"``:` `    ``# Given string``    ``S ``=` `"abaabac"` `    ``# Given queries``    ``queries ``=` `[ [ ``2``, ``6` `], [ ``1``, ``7` `] ]` `    ``# Function Call``    ``maxDiffFreq(queries, S)` `# This code is contributed by chitranayal`

## C#

 `// C# program for the above approach``using` `System;``using` `System.Collections.Generic;``class` `GFG``{``    ` `    ``// Funciton to find difference between maximum and``    ``// minimum frequency of a character in given range``    ``static` `void` `maxDiffFreq(List> queries, ``string` `S)``    ``{``        ` `        ``// Stores length of string``        ``int` `N = S.Length;``      ` `        ``// Stores count of queries``        ``int` `Q = queries.Count;``      ` `        ``// Iterate over the characters``        ``// of the string``        ``for` `(``int` `i = 0; i < Q; ++i)``        ``{``      ` `            ``// Stores l-value of a query``            ``int` `l = queries[i].Item1 - 1;``      ` `            ``// Stores r-value of a query``            ``int` `r = queries[i].Item2 - 1;``            ``int``[] freq = ``new` `int``;``      ` `            ``// Store count of every character``            ``// laying in range [l, r]``            ``for` `(``int` `j = l; j <= r; j++)``            ``{``      ` `                ``// Update frequency of``                ``// current character``                ``freq[S[j] - ``'a'``]++;``            ``}``      ` `            ``// Stores maximum frequency``            ``// of characters in given range``            ``int` `mx = 0;``      ` `            ``// Stores minimum frequency``            ``// of characters in given range``            ``int` `mn = 99999999;``      ` `            ``// Iterate over all possible characters``            ``// of the given string``            ``for` `(``int` `j = 0; j < 26; j++)``            ``{``      ` `                ``// Update mx``                ``mx = Math.Max(mx, freq[j]);``      ` `                ``// If (j + 'a') is present``                ``if` `(freq[j] != 0)``                    ``mn = Math.Min(mn, freq[j]);``            ``}``      ` `            ``// difference between max and min``            ``Console.WriteLine(mx - mn);``        ``}``    ``}   ` `  ``// Driver code``  ``static` `void` `Main()``  ``{``      ` `    ``// Given string``    ``string` `S = ``"abaabac"``;``  ` `    ``// Given queries``    ``List> queries = ``new` `List>();``    ``queries.Add(``new` `Tuple<``int``, ``int``>(2, 6));``    ``queries.Add(``new` `Tuple<``int``, ``int``>(1, 7));``  ` `    ``// Function Call``    ``maxDiffFreq(queries, S);``  ``}``}` `// This code is contributed by divyeshrabadiya07`
Output:
```1
3```

Efficient Approach: The idea is to use a 2D-Fenwick tree to store the frequency of each character. Follow the steps below to solve the problem:

1. Create a two-dimensional Fenwick tree that stores the information about each character from ‘a’ to ‘z’.
2. Then for each query, count the frequencies of each character in the given range using the Fenwick tree.
3. From the frequencies found above, get the maximum and the minimum frequency.
4. Print the difference between the maximum and minimum frequency as the answer.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``using` `namespace` `std;` `// Function to update frequency of``// a character in Fenwick tree``void` `update(``int` `BIT, ``int` `idx,``            ``int` `i, ``int` `val)``{``    ``while` `(i < 10005) {` `        ``// Update frequency of (idx + 'a')``        ``BIT[idx][i] += val;` `        ``// Update i``        ``i = i + (i & (-i));``    ``}``}` `// Function to find the frequency of``// a character (idx + 'a') in range [1, i]``int` `query(``int` `BIT, ``int` `idx, ``int` `i)``{` `    ``// Stores frequency of character, (idx + 'a')``    ``// in range [1, i]``    ``int` `ans = 0;` `    ``while` `(i > 0) {` `        ``// Update ans``        ``ans += BIT[idx][i];` `        ``// Update i``        ``i = i - (i & (-i));``    ``}``    ``return` `ans;``}` `// Function to find difference between maximum and``// minimum frequency of a character in given range``void` `maxDiffFreq(string s, vector > queries)``{` `    ``// BIT[i][j]: Stores frequency of (i + 'a')``    ``// If j is a power of 2, then it stores``    ``// the frequency (i + 'a') of  from [1, j]``    ``int` `BIT;` `    ``// Stores length of string``    ``int` `n = s.size();` `    ``// Iterate over the characters``    ``// of the string``    ``for` `(``int` `i = 0; i < n; i++) {` `        ``// Update the frequency of``        ``// s[i] in fenwick tree``        ``update(BIT, s[i] - ``'a'``, i + 1, 1);``    ``}` `    ``// Stores count of queries``    ``int` `Q = queries.size();` `    ``// Iterate over all the queries``    ``for` `(``int` `i = 0; i < Q; ++i) {` `        ``// Stores maximum frequency of``        ``// a character in range [l, r]``        ``int` `mx = 0;` `        ``// Stores minimum frequency of``        ``// a character in range [l, r]` `        ``int` `mn = INT_MAX;``        ``int` `l = queries[i].first;``        ``int` `r = queries[i].second;` `        ``// Iterate over all possible characters``        ``for` `(``int` `j = 0; j < 26; j++) {` `            ``// Stores frequency of (j + 'a')``            ``// in range [1, r]``            ``int` `p = query(BIT, j, r);` `            ``// Stores frequency of (j + 'a')``            ``// in range [1, l - 1]``            ``int` `q = query(BIT, j, l - 1);` `            ``// Update mx``            ``mx = max(mx, p - q);` `            ``// If a character (i + 'a') present``            ``// in range [l, r]``            ``if` `(p > 0) {` `                ``// Update mn``                ``mn = min(mn, p - q);``            ``}``        ``}` `        ``// Print the difference between``        ``// max and min freq``        ``cout << mx - mn << endl;``    ``}``}` `// Driver Code``int` `main()``{` `    ``// Given string``    ``string S = ``"abaabac"``;` `    ``// Given queries``    ``vector > queries``        ``= { { 2, 6 }, { 1, 7 } };` `    ``// Function Call``    ``maxDiffFreq(S, queries);``}`

## Java

 `// Java program for the above approach``import` `java.util.*;` `class` `GFG``{` `// Function to update frequency of``// a character in Fenwick tree``static` `void` `update(``int` `BIT[][], ``int` `idx,``            ``int` `i, ``int` `val)``{``    ``while` `(i < ``10005``)``    ``{` `        ``// Update frequency of (idx + 'a')``        ``BIT[idx][i] += val;` `        ``// Update i``        ``i = i + (i & (-i));``    ``}``}` `// Function to find the frequency of``// a character (idx + 'a') in range [1, i]``static` `int` `query(``int` `BIT[][], ``int` `idx, ``int` `i)``{` `    ``// Stores frequency of character, (idx + 'a')``    ``// in range [1, i]``    ``int` `ans = ``0``;` `    ``while` `(i > ``0``) {` `        ``// Update ans``        ``ans += BIT[idx][i];` `        ``// Update i``        ``i = i - (i & (-i));``    ``}``    ``return` `ans;``}` `// Function to find difference between maximum and``// minimum frequency of a character in given range``static` `void` `maxDiffFreq(String s, ``int` `[][]queries)``{` `    ``// BIT[i][j]: Stores frequency of (i + 'a')``    ``// If j is a power of 2, then it stores``    ``// the frequency (i + 'a') of  from [1, j]``    ``int``[][] BIT = ``new` `int``[``26``][``10005``];` `    ``// Stores length of String``    ``int` `n = s.length();` `    ``// Iterate over the characters``    ``// of the String``    ``for` `(``int` `i = ``0``; i < n; i++) {` `        ``// Update the frequency of``        ``// s[i] in fenwick tree``        ``update(BIT, s.charAt(i) - ``'a'``, i + ``1``, ``1``);``    ``}` `    ``// Stores count of queries``    ``int` `Q = queries.length;` `    ``// Iterate over all the queries``    ``for` `(``int` `i = ``0``; i < Q; ++i) {` `        ``// Stores maximum frequency of``        ``// a character in range [l, r]``        ``int` `mx = ``0``;` `        ``// Stores minimum frequency of``        ``// a character in range [l, r]` `        ``int` `mn = Integer.MAX_VALUE;``        ``int` `l = queries[i][``0``];``        ``int` `r = queries[i][``1``];` `        ``// Iterate over all possible characters``        ``for` `(``int` `j = ``0``; j < ``26``; j++) {` `            ``// Stores frequency of (j + 'a')``            ``// in range [1, r]``            ``int` `p = query(BIT, j, r);` `            ``// Stores frequency of (j + 'a')``            ``// in range [1, l - 1]``            ``int` `q = query(BIT, j, l - ``1``);` `            ``// Update mx``            ``mx = Math.max(mx, p - q);` `            ``// If a character (i + 'a') present``            ``// in range [l, r]``            ``if` `(p > ``0``) {` `                ``// Update mn``                ``mn = Math.min(mn, p - q);``            ``}``        ``}` `        ``// Print the difference between``        ``// max and min freq``        ``System.out.print(mx - mn +``"\n"``);``    ``}``}` `// Driver Code``public` `static` `void` `main(String[] args)``{` `    ``// Given String``    ``String S = ``"abaabac"``;` `    ``// Given queries``    ``int` `[][]queries``        ``= { { ``2``, ``6` `}, { ``1``, ``7` `} };` `    ``// Function Call``    ``maxDiffFreq(S, queries);``}``}` `// This code is contributed by shikhasingrajput`

## Python3

 `# Python3 program for the above approach``import` `sys` `# Function to update frequency of``# a character in Fenwick tree``def` `update(BIT, idx, i, val) :``    ``while` `(i < ``10005``) :``    ` `      ``# Update frequency of (idx + 'a')``      ``BIT[idx][i] ``+``=` `val``    ` `      ``# Update i``      ``i ``=` `i ``+` `(i & (``-``i))``      ` `# Function to find the frequency of``# a character (idx + 'a') in range [1, i]``def` `query(BIT, idx, i) :` `    ``# Stores frequency of character, (idx + 'a')``    ``# in range [1, i]``    ``ans ``=` `0``    ``while` `(i > ``0``) :``    ` `      ``# Update ans``      ``ans ``+``=` `BIT[idx][i]``    ` `      ``# Update i``      ``i ``=` `i ``-` `(i & (``-``i))` `    ``return` `ans``    ` `# Function to find difference between maximum and``# minimum frequency of a character in given range``def` `maxDiffFreq(s, queries) :` `    ``# BIT[i][j]: Stores frequency of (i + 'a')``    ``# If j is a power of 2, then it stores``    ``# the frequency (i + 'a') of  from [j]``    ``BIT ``=` `[[``0` `for` `i ``in` `range``(``10005``)] ``for` `j ``in` `range``(``26``)]``    ` `    ``# Stores length of String``    ``n ``=` `len``(s)``    ` `    ``# Iterate over the characters``    ``# of the String``    ``for` `i ``in` `range``(n) :``    ` `      ``# Update the frequency of``      ``# s[i] in fenwick tree``      ``update(BIT, ``ord``(s[i]) ``-` `ord``(``'a'``), i ``+` `1``, ``1``)``    ` `    ``# Stores count of queries``    ``Q ``=` `len``(queries)``    ` `    ``# Iterate over all the queries``    ``for` `i ``in` `range``(Q) :``    ` `      ``# Stores maximum frequency of``      ``# a character in range [l, r]``      ``mx ``=` `0``    ` `      ``# Stores minimum frequency of``      ``# a character in range [l, r]``      ``mn ``=` `sys.maxsize``      ``l ``=` `queries[i][``0``]``      ``r ``=` `queries[i][``1``]``    ` `      ``# Iterate over all possible characters``      ``for` `j ``in` `range``(``26``) :``    ` `        ``# Stores frequency of (j + 'a')``        ``# in range [1, r]``        ``p ``=` `query(BIT, j, r)``    ` `        ``# Stores frequency of (j + 'a')``        ``# in range [1, l - 1]``        ``q ``=` `query(BIT, j, l ``-` `1``)``    ` `        ``# Update mx``        ``mx ``=` `max``(mx, p ``-` `q)``    ` `        ``# If a character (i + 'a') present``        ``# in range [l, r]``        ``if` `(p > ``0``) :``    ` `          ``# Update mn``          ``mn ``=` `min``(mn, p ``-` `q)``    ` `      ``# Print the difference between``      ``# max and min freq``      ``print``(mx ``-` `mn)``      ` `# Given String``S ``=` `"abaabac"` `# Given queries``queries ``=` `[ [ ``2``, ``6` `], [ ``1``, ``7` `] ]` `# Function Call``maxDiffFreq(S, queries)` `# This code is contributed by divyesh072019.`

## C#

 `// C# program for the above approach``using` `System;``public` `class` `GFG``{` `  ``// Function to update frequency of``  ``// a character in Fenwick tree``  ``static` `void` `update(``int` `[,]BIT, ``int` `idx,``                     ``int` `i, ``int` `val)``  ``{``    ``while` `(i < 10005)``    ``{` `      ``// Update frequency of (idx + 'a')``      ``BIT[idx,i] += val;` `      ``// Update i``      ``i = i + (i & (-i));``    ``}``  ``}` `  ``// Function to find the frequency of``  ``// a character (idx + 'a') in range [1, i]``  ``static` `int` `query(``int` `[,]BIT, ``int` `idx, ``int` `i)``  ``{` `    ``// Stores frequency of character, (idx + 'a')``    ``// in range [1, i]``    ``int` `ans = 0;``    ``while` `(i > 0)``    ``{` `      ``// Update ans``      ``ans += BIT[idx,i];` `      ``// Update i``      ``i = i - (i & (-i));``    ``}``    ``return` `ans;``  ``}` `  ``// Function to find difference between maximum and``  ``// minimum frequency of a character in given range``  ``static` `void` `maxDiffFreq(String s, ``int` `[,]queries)``  ``{` `    ``// BIT[i,j]: Stores frequency of (i + 'a')``    ``// If j is a power of 2, then it stores``    ``// the frequency (i + 'a') of  from [1, j]``    ``int``[,] BIT = ``new` `int``[26, 10005];` `    ``// Stores length of String``    ``int` `n = s.Length;` `    ``// Iterate over the characters``    ``// of the String``    ``for` `(``int` `i = 0; i < n; i++)``    ``{` `      ``// Update the frequency of``      ``// s[i] in fenwick tree``      ``update(BIT, s[i] - ``'a'``, i + 1, 1);``    ``}` `    ``// Stores count of queries``    ``int` `Q = queries.GetLength(0);` `    ``// Iterate over all the queries``    ``for` `(``int` `i = 0; i < Q; ++i)``    ``{` `      ``// Stores maximum frequency of``      ``// a character in range [l, r]``      ``int` `mx = 0;` `      ``// Stores minimum frequency of``      ``// a character in range [l, r]``      ``int` `mn = ``int``.MaxValue;``      ``int` `l = queries[i, 0];``      ``int` `r = queries[i, 1];` `      ``// Iterate over all possible characters``      ``for` `(``int` `j = 0; j < 26; j++)``      ``{` `        ``// Stores frequency of (j + 'a')``        ``// in range [1, r]``        ``int` `p = query(BIT, j, r);` `        ``// Stores frequency of (j + 'a')``        ``// in range [1, l - 1]``        ``int` `q = query(BIT, j, l - 1);` `        ``// Update mx``        ``mx = Math.Max(mx, p - q);` `        ``// If a character (i + 'a') present``        ``// in range [l, r]``        ``if` `(p > 0)``        ``{` `          ``// Update mn``          ``mn = Math.Min(mn, p - q);``        ``}``      ``}` `      ``// Print the difference between``      ``// max and min freq``      ``Console.Write(mx - mn +``"\n"``);``    ``}``  ``}` `  ``// Driver Code``  ``public` `static` `void` `Main(String[] args)``  ``{` `    ``// Given String``    ``String S = ``"abaabac"``;` `    ``// Given queries``    ``int` `[,]queries``      ``= { { 2, 6 }, { 1, 7 } };` `    ``// Function Call``    ``maxDiffFreq(S, queries);``  ``}``}` `// This code is contributed by shikhasingrajput`
Output:
```1
3```

Time Complexity: O(|Q| * log(N) * 26)
Auxiliary Space: O(N * 26)

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

My Personal Notes arrow_drop_up