Current execution complexity is O(lq) while l is the length of the input array and q is the number of queries.
The complexity of each query is O(l).
With proper data structure, you can store the input data in such way that each query will be O(1). For example, you can create a table where each line will present the letter (from a
to z
, for this example let's assume we get only lower case letters). Each column will present the number of times, the given letter has occurred till (and including) the index of this column.
For instance if the input is aabz
, the table will look like this:
| 0 1 2 3------------------------ a | 1 2 2 2 b | 0 0 1 1 . | . . . . . | . . . . y | 0 0 0 0 z | 0 0 0 1
In such case if you need to check number of occurrence of the letter at index 2 till (and including) this index, all you need to do is
- Check the letter at index 2 in the input string (
'b'
) - Check the value in the lookup table at [
'b'
][2] --> 1
The complexity to create such table is O(l). Here is an example for the code to build such table:
#define CHARS_SIZE ('z' - 'a'+ 1)// 'arr' - is the input array of chars// 'len' - length of the input array// 'lookup' - pointer to a zeroed (cleared) array of size: CHARS_SIZE * len * sizeof(*lookup)void build_lookup(const char *arr, int len, int *lookup){ int char_val; // normalize the letter to integer value between 0 (for 'a') and 25 (for 'z') char_val = arr[0] - 'a'; lookup[char_val*len] = 1; // 'i' indicates the column index in the table for (int i = 1; i < len; ++i) { char_val = arr[i] - 'a'; // update the number of occurrences for each letter a..z at column 'i' for (int char_iter = 0; char_iter < CHARS_SIZE; ++char_iter) { if (char_iter != char_val) { // same value as the previous one lookup[char_iter*len + i] = lookup[char_iter*len + i - 1]; } else { // +1 to the value in the previous value lookup[char_iter*len + i] = lookup[char_iter*len + i - 1] + 1; } } }}
The query, in such case, would be:
int occ(const char *arr, int len, const int *lookup, int idx){ // normalize the letter to integer value between 0 (for 'a') and 25 (for 'z') int char_val = arr[idx] - 'a'; return lookup[char_val * len + idx];}
Here is your code with few additions of what I explained above: https://godbolt.org/z/zaY4RL
Note that I haven't tested it so there probably a few bugs so use it as a reference and not as a full solution.