给定一个仅由小写字母组成的字符串str和一个数组arr[][]表示对给定字符串str 的范围查询,其中每个查询包含 3 个整数 {L, R, N} 这样对于每个查询我们必须输出查询中指定的给定范围 [L, R] 中的第N个最小字符。
例子:
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’
朴素的方法:朴素的方法是运行从L到R的循环并生成此范围内的子字符串。一旦子被发现,排序子找到N的排序字符串个字符。
时间复杂度分析:
- 在最坏的情况下,从L遍历到R的复杂度为O(N) 。
- 对子字符串进行排序的复杂度为O(N * Log(N)) 。
- 由于我们对每个查询的子字符串进行排序,因此,整体时间复杂度为O(N 2 * Log(N)) 。
有效的方法:这个想法是利用二维哈希表。哈希表H[][]被初始化为N 行和26 列,其中 N 表示字符串的长度,26 表示共有 26 个小写字母。
hashtable 背后的想法是,对于每个索引i ,其中 ‘i’ 的范围从 1 到 N,我们跟踪第i个索引上或之前的 26 个小写字母中的每一个出现的次数。为此,使用散列,其中每个字符都被视为一个数字,如下所示:
'a' -> 0
'b' -> 1
.
.
.
'z' -> 25
因此,对于每个查询 {L, R, N},我们通过从H[R][j]中减去H[L – 1][j]的元素来获得给定范围内每个字符的出现次数,其中 j 的范围为0 到 25 的哈希表形式。在这之后,我们需要做的就是从 0 到 25 遍历并添加结果数组的内容。每当总和等于或超过N 时,表示该索引的字符就是必需的答案。
例如,如果在第5个索引 (j = 4) 上,到那时为止的总和超过 N,则答案变为“e”,因为 4 相当于字符“e”。以下是示例案例的图示:
该图像描述了与给定字符串对应的哈希表。对于范围[2, 4] ,我们从H[4] 中减去H[2 – 1]中的内容。我们得到:
显然,这个结果数组包含范围 [2, 4] 内的元素计数。所以我们简单地从 0 到 25 遍历并计算内容,直到我们到达 N。在 N = 1 的查询中,答案是“b”,对于 N = 2,答案变成“c”,依此类推。
下面是上述方法的实现:
C++
// C++ implementation to find the Nth
// smallest character in a given range
// of a string
#include
using namespace std;
// Query structure to represent a query range
// along with n
struct Query {
int l, r, n;
};
// Function to print the Nth smallest
// character for a given range in a string
int findSmallest(string s, Query q[], int m)
{
// Integer N contains the
// length of the string s
int N = s.length();
// We initialise our hash array and
// set all the elements to 0
int H[N + 1][26];
memset(H, 0, sizeof(H));
// We preprocess our string in which we
// update the current character
// as well as add the H[i - 1]th
// array to H[i]
for (int i = 1; i <= N; i++) {
// Incrementing the frequency of
// ith row based on the occurrence
// of the characters up to i-th index
++H[i][s[i - 1] - 'a'];
// Adding the values of the array at
// the previous index to the next index
for (int j = 0; j < 26; j++) {
H[i][j] += H[i - 1][j];
}
}
// We traverse from 0 to m to
// fetch all the queries
for (int j = 0; j < m; j++) {
// Extracting L, R and N
// from the query array q
int l = q[j].l, r = q[j].r,
n = q[j].n;
// The initial sum is set to 0
int sum = 0;
// We subtract H[l-1] from h[r]
// and add it to the sum
for (int i = 0; i < 26; i++) {
sum += H[r][i] - H[l - 1][i];
// Whenever the sum is greater than
// or equal to N, the equivalent
// character of the index is our
// nth smallest character
if (sum >= n) {
cout << (char)('a' + i) << "\n";
break;
}
}
}
}
// Driver code
int main()
{
// Input string s
string s = "afbccdeb";
// Query array q, for each q
// it contains l, r and n
Query q[] = { { 2, 4, 1 },
{ 1, 6, 4 },
{ 1, 8, 7 } };
int x = sizeof(q) / sizeof(q[0]);
findSmallest(s, q, x);
}
Java
// JAVA implementation to find the Nth
// smallest character for a given range
// in a string
import java.io.*;
import java.util.*;
class GFG {
// Query class to represent a query range
// along with n
public static class Query {
public int l, r, n;
// Constructor for the Query class which
// takes three integers L, R, N
public Query(int l, int r, int n)
{
this.l = l;
this.r = r;
this.n = n;
}
}
// Function to print the Nth smallest
// character for a given range in a string
public static void printSmallest(String s, Query[] q)
{
// Integer N contains the
// length of the string s
int N = s.length();
// We initialise our hash array and
// set all the elements to 0
int[][] H = new int[N + 1][26];
// We preprocess our string in which we
// update the current character
// as well as add the H[i - 1]th
// array to H[i]
for (int i = 1; i <= N; i++) {
// Incrementing the frequency of
// ith row based on the occurrence
// of the characters up to i-th index
++H[i][s.charAt(i - 1) - 'a'];
// Adding the values of the array at
// the previous index to the next index
for (int j = 0; j < 26; j++) {
H[i][j] += H[i - 1][j];
}
}
// Integer m contains the
// number of queries
int m = q.length;
// We traverse from 0 to m to
// fetch all the queries
for (int j = 0; j < m; j++) {
// Extracting l, r and n
// from the query array q
int l = q[j].l, r = q[j].r,
n = q[j].n;
// The initial sum is set to 0
int sum = 0;
// We subtract H[l-1] from h[r]
// and add it to the sum
for (int i = 0; i < 26; i++) {
sum += H[r][i] - H[l - 1][i];
// Whenever the sum is greater than
// or equal to N, the equivalent
// character of the index is our
// nth smallest character
if (sum >= n) {
System.out.println((char)('a' + i));
break;
}
}
}
}
// Driver code
public static void main(String args[])
{
// Input string s
String s = "afbccdeb";
// Query array q, for each q
// it contains l, r and n
Query[] q = { new Query(2, 4, 1),
new Query(1, 6, 4),
new Query(1, 8, 7) };
// Calling the function
printSmallest(s, q);
}
}
Python3
# Python3 implementation to find the Nth
# smallest character in a given range
# of a string
# Function to print the Nth smallest
# character for a given range in a string
def findSmallest(s, q, m):
# Integer N contains the
# length of the s
N = len(s)
# We initialise our hash array and
# set all the elements to 0
H = [[0 for i in range(26)]for i in range(N + 1)]
# We preprocess our in which we
# update the current character
# as well as add the H[i - 1]th
# array to H[i]
for i in range(1, N + 1):
# Incrementing the frequency of
# ith row based on the occurrence
# of the characters up to i-th index
H[i][ord(s[i - 1]) - ord('a')] += 1
# Adding the values of the array at
# the previous index to the next index
for j in range(26):
H[i][j] += H[i - 1][j]
# We traverse from 0 to m to
# fetch all the queries
for j in range(m):
# Extracting L, R and N
# from the query array q
l = q[j][0]
r = q[j][1]
n = q[j][2]
# The initial sum is set to 0
sum = 0
# We subtract H[l-1] from h[r]
# and add it to the sum
for i in range(26):
sum += H[r][i] - H[l - 1][i]
# Whenever the sum is greater than
# or equal to N, the equivalent
# character of the index is our
# nth smallest character
if (sum >= n):
print(chr(ord('a') + i))
break
# Driver code
if __name__ == '__main__':
# Input s
s = "afbccdeb"
# Query array q, for each q
# it contains l, r and n
q = [ [ 2, 4, 1 ],
[ 1, 6, 4 ],
[ 1, 8, 7 ] ]
x = len(q)
findSmallest(s, q, x)
# This code is contributed by mohit kumar 29
C#
// C# implementation to find the Nth
// smallest character for a given range
// in a string
using System;
class GFG {
// Query class to represent a query range
// along with n
public class Query {
public int l, r, n;
// Constructor for the Query class which
// takes three integers L, R, N
public Query(int l, int r, int n)
{
this.l = l;
this.r = r;
this.n = n;
}
}
// Function to print the Nth smallest
// character for a given range in a string
public static void printSmallest(String s, Query[] q)
{
// int N contains the
// length of the string s
int N = s.Length;
// We initialise our hash array and
// set all the elements to 0
int[,] H = new int[N + 1,26];
// We preprocess our string in which we
// update the current character
// as well as add the H[i - 1]th
// array to H[i]
for (int i = 1; i <= N; i++) {
// Incrementing the frequency of
// ith row based on the occurrence
// of the characters up to i-th index
++H[i, s[i - 1] - 'a'];
// Adding the values of the array at
// the previous index to the next index
for (int j = 0; j < 26; j++) {
H[i, j] += H[i - 1, j];
}
}
// int m contains the
// number of queries
int m = q.Length;
// We traverse from 0 to m to
// fetch all the queries
for (int j = 0; j < m; j++) {
// Extracting l, r and n
// from the query array q
int l = q[j].l, r = q[j].r,
n = q[j].n;
// The initial sum is set to 0
int sum = 0;
// We subtract H[l-1] from h[r]
// and add it to the sum
for (int i = 0; i < 26; i++) {
sum += H[r, i] - H[l - 1, i];
// Whenever the sum is greater than
// or equal to N, the equivalent
// character of the index is our
// nth smallest character
if (sum >= n) {
Console.WriteLine((char)('a' + i));
break;
}
}
}
}
// Driver code
public static void Main(String []args)
{
// Input string s
String s = "afbccdeb";
// Query array q, for each q
// it contains l, r and n
Query[] q = { new Query(2, 4, 1),
new Query(1, 6, 4),
new Query(1, 8, 7) };
// Calling the function
printSmallest(s, q);
}
}
// This code is contributed by Rajput-Ji
b
c
e
时间复杂度分析:
- 对于上述方法,尽管预处理由两个循环组成,但第二个循环运行的次数是恒定的(26)。因此,预处理所需的时间是O(N) 。
- 预处理后,对于每个查询,字符以恒定时间返回,这里 for 循环再次运行恒定次数(26)。因此,回答每个查询所花费的时间是O(1) 。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live