 Open in App
Not now

# Sum of indices of Characters removed to obtain an Empty String based on given conditions

• Difficulty Level : Medium
• Last Updated : 15 Sep, 2022

Given a string str, consisting of lowercase English alphabets, the task is to calculate the sum of indices(1-based indexing) of the characters removed to obtain an empty string by the following operations:

• Remove the smallest alphabet in the string.
• For multiple occurrences of the smallest alphabet, remove the one present at the smallest index.
• After removal of each character, the indices of all characters on its right reduces by 1.

Examples:

Input: str = “aba”
Output:
Explanation:aba” -> “ba”, Sum = 1
“ba” -> “b”, Sum = 1 + 2 = 3
“b” -> “”, Sum = 3 + 1 = 4

Input: str = “geeksforgeeks”
Output: 41

Naive Approach:
Follow the steps below to solve the problem:

• Find the smallest character with minimum index.
• Delete that character from string and shift all the characters one index to the right.
• Repeat the above steps until the string is empty.

Time Complexity: O(N^2)
Auxiliary Space: O(N)

Efficient Approach: The above approach can be optimized using Segment Tree and Hashing. Follow the steps below to solve the problem:

• It can be observed that only the indices on the right of the deleted character are affected, that is, they need to be shifted by one position.
• Store the indices of the characters in a HashMap
• Process the characters in the HashMap.
• Find the number of elements which are left to the current index of the character, which are already deleted from the string, using Segment Tree.
• Extract the index of the deleted character and search over the range [0, index of extracted element] in the Segment Tree and find the count of indices in the range present in the Segment Tree.
• Add index of extracted element – count to the answer and insert the index of the currently deleted element into the Segment Tree.
• Repeat the above steps until the string is empty.

Below is the implementation of the above approach:

## C++

 `// C++ Program to implement` `// the above approach` `#include ` `using` `namespace` `std;`   `// Function to add index of the deleted character` `void` `add_seg(``int` `seg[], ``int` `start, ``int` `end, ``int` `current,` `             ``int` `index)` `{`   `    ``// If index is beyond the range` `    ``if` `(index > end or index < start)` `        ``return``;`   `    ``// Insert the index of the deleted` `    ``// character` `    ``if` `(start == end) {` `        ``seg[current] = 1;` `        ``return``;` `    ``}` `    ``int` `mid = (start + end) / 2;`   `    ``// Search over the subtrees to find the` `    ``// desired index` `    ``add_seg(seg, start, mid, 2 * current + 1, index);` `    ``add_seg(seg, mid + 1, end, 2 * current + 2, index);` `    ``seg[current]` `        ``= seg[2 * current + 1] + seg[2 * current + 2];` `}`   `// Function to return count of deleted indices` `// which are to the left of the current index` `int` `deleted(``int` `seg[], ``int` `l, ``int` `r, ``int` `start, ``int` `end,` `            ``int` `current)` `{` `    ``if` `(end < l or start > r)` `        ``return` `0;` `    ``if` `(start >= l and end <= r)` `        ``return` `seg[current];` `    ``int` `mid = (start + end) / 2;` `    ``return` `deleted(seg, l, r, start, mid, 2 * current + 1)` `           ``+ deleted(seg, l, r, mid + 1, end,` `                     ``2 * current + 2);` `}`   `// Function to generate the ` `// sum of indices ` `void` `sumOfIndices(string s)` `{` `    ``int` `N = s.size();` `    ``int` `x = ``int``(``ceil``(log2(N)));` `    ``int` `seg_size = 2 * (``int``)``pow``(2, x) - 1;` `    ``int` `segment[seg_size] = { 0 };`   `    ``int` `count = 0;`   `    ``// Stores the original index of the` `    ``// characters in sorted order of key` `    ``map<``int``, queue<``int``> > fre;` `    ``for` `(``int` `i = 0; i < N; i++) {` `        ``fre[s[i]].push(i);` `    ``}`   `    ``// Traverse the map` `    ``while` `(fre.empty() == ``false``) {`   `        ``// Extract smallest index` `        ``// of smallest character` `        ``auto` `it = fre.begin();`   `        ``// Delete the character from the map` `        ``// if it has no remaining occurrence` `        ``if` `(it->second.empty() == ``true``)` `            ``fre.erase(it->first);` `        ``else` `{`   `            ``// Stores the original index` `            ``int` `original_index` `                ``= it->second.front();`   `            ``// Count of elements removed to` `            ``// the left of current character` `            ``int` `curr_index` `                ``= deleted(segment, 0, original_index - 1,` `                          ``0, N - 1, 0);`   `            ``// Current index of the current character` `            ``int` `new_index` `                ``= original_index - curr_index;`   `            ``// For 1-based indexing` `            ``count += new_index + 1;`   `            ``// Insert the deleted index` `            ``// in the segment tree` `            ``add_seg(segment, 0, N - 1,` `                    ``0, original_index);` `            ``it->second.pop();` `        ``}` `    ``}`   `    ``// Final answer` `    ``cout << count << endl;` `}`   `// Driver Code` `int` `main()` `{` `    ``string s = ``"geeksforgeeks"``;` `    ``sumOfIndices(s);` `}`

## Java

 `// Java program to implement ` `// the above approach ` `import` `java.io.*;` `import` `java.lang.*;` `import` `java.util.*;`   `class` `GFG{`   `// Function to add index of the deleted character` `static` `void` `add_seg(``int` `seg[], ``int` `start, ``int` `end,` `                    ``int` `current, ``int` `index)` `{` `    `  `    ``// If index is beyond the range` `    ``if` `(index > end || index < start)` `        ``return``;`   `    ``// Insert the index of the deleted` `    ``// character` `    ``if` `(start == end) ` `    ``{` `        ``seg[current] = ``1``;` `        ``return``;` `    ``}` `    ``int` `mid = (start + end) / ``2``;`   `    ``// Search over the subtrees to find the` `    ``// desired index` `    ``add_seg(seg, start, mid, ``2` `* current + ``1``, index);` `    ``add_seg(seg, mid + ``1``, end, ``2` `* current + ``2``, index);` `    ``seg[current] = seg[``2` `* current + ``1``] + ` `                   ``seg[``2` `* current + ``2``];` `}`   `// Function to return count of deleted indices` `// which are to the left of the current index` `static` `int` `deleted(``int` `seg[], ``int` `l, ``int` `r, ``int` `start,` `                   ``int` `end, ``int` `current)` `{` `    ``if` `(end < l || start > r)` `        ``return` `0``;` `    ``if` `(start >= l && end <= r)` `        ``return` `seg[current];` `        `  `    ``int` `mid = (start + end) / ``2``;` `    `  `    ``return` `deleted(seg, l, r, start, mid,` `                   ``2` `* current + ``1``) + ` `           ``deleted(seg, l, r, mid + ``1``, end,` `                   ``2` `* current + ``2``);` `}`   `// Function to generate the` `// sum of indices` `static` `void` `sumOfIndices(String s)` `{` `    ``int` `N = s.length();` `    ``int` `x = (``int``)(Math.ceil(Math.log(N) / Math.log(``2``)));` `    ``int` `seg_size = ``2` `* (``int``)Math.pow(``2``, x) - ``1``;` `    ``int` `segment[] = ``new` `int``[seg_size];`   `    ``int` `count = ``0``;`   `    ``// Stores the original index of the` `    ``// characters in sorted order of key` `    ``TreeMap> fre = ``new` `TreeMap<>();` `    ``for``(``int` `i = ``0``; i < N; i++)` `    ``{` `        ``int` `key = (``int``)(s.charAt(i));` `        ``ArrayDeque que = fre.getOrDefault(` `            ``key, ``new` `ArrayDeque<>());` `        ``que.addLast(i);` `        ``fre.put(key, que);` `    ``}`   `    ``// Traverse the map` `    ``while` `(!fre.isEmpty())` `    ``{` `        `  `        ``// Extract smallest index` `        ``// of smallest character` `        ``int` `it = fre.firstKey();`   `        ``// Delete the character from the map` `        ``// if it has no remaining occurrence` `        ``if` `(fre.get(it).size() == ``0``)` `            ``fre.remove(it);` `        ``else` `        ``{` `            ``ArrayDeque que = fre.get(it);`   `            ``// Stores the original index` `            ``int` `original_index = que.getFirst();` `            ``// System.out.println(original_index);`   `            ``// Count of elements removed to` `            ``// the left of current character` `            ``int` `curr_index = deleted(segment, ``0``,` `                                     ``original_index - ``1``,` `                                     ``0``, N - ``1``, ``0``);`   `            ``// Current index of the current character` `            ``int` `new_index = original_index - curr_index;`   `            ``// For 1-based indexing` `            ``count += new_index + ``1``;`   `            ``// Insert the deleted index` `            ``// in the segment tree` `            ``add_seg(segment, ``0``, N - ``1``, ``0``,` `                    ``original_index);`   `            ``que.removeFirst();` `            ``fre.put(it, que);` `        ``}` `    ``}`   `    ``// Final answer` `    ``System.out.println(count);` `}`   `// Driver Code` `public` `static` `void` `main(String[] args)` `{` `    ``String s = ``"geeksforgeeks"``;` `    `  `    ``sumOfIndices(s);` `}` `}`   `// This code is contributed by Kingash`

## Python3

 `# Python3 program to implement the above approach` `import` `math, collections`   `# Function to add index of the deleted character` `def` `add_seg(seg, start, end, current, index):` `    ``# If index is beyond the range` `    ``if` `(index > end ``or` `index < start):` `        ``return` ` `  `    ``# Insert the index of the deleted` `    ``# character` `    ``if` `(start ``=``=` `end):` `        ``seg[current] ``=` `1` `        ``return` `    ``mid ``=` `int``((start ``+` `end) ``/` `2``)` ` `  `    ``# Search over the subtrees to find the` `    ``# desired index` `    ``add_seg(seg, start, mid, ``2` `*` `current ``+` `1``, index)` `    ``add_seg(seg, mid ``+` `1``, end, ``2` `*` `current ``+` `2``, index)` `    ``seg[current] ``=` `seg[``2` `*` `current ``+` `1``] ``+` `seg[``2` `*` `current ``+` `2``]` ` `  `# Function to return count of deleted indices` `# which are to the left of the current index` `def` `deleted(seg, l, r, start, end, current):` `    ``if` `(end < l ``or` `start > r):` `        ``return` `0` `    ``if` `(start >``=` `l ``and` `end <``=` `r):` `        ``return` `seg[current]` `         `  `    ``mid ``=` `int``((start ``+` `end) ``/` `2``)` `     `  `    ``return` `deleted(seg, l, r, start, mid, ``2` `*` `current ``+` `1``) ``+` `deleted(seg, l, r, mid ``+` `1``, end, ``2` `*` `current ``+` `2``)` ` `  `# Function to generate the` `# sum of indices` `def` `sumOfIndices(s):` `    ``N ``=` `len``(s)` `    ``x ``=` `(``int``)(math.ceil(math.log(N) ``/` `math.log(``2``)))` `    ``seg_size ``=` `2` `*` `pow``(``2``, x) ``-` `1` `    ``segment ``=` `[``0``]``*``(seg_size)` ` `  `    ``count ``=` `4` ` `  `    ``# Stores the original index of the` `    ``# characters in sorted order of key` `    ``fre ``=` `{}` `    ``for` `i ``in` `range``(N):` `        ``key ``=` `(``ord``)(s[i])` `        ``if` `key ``in` `fre:` `            ``que ``=` `fre[key]` `        ``else``:` `            ``que ``=` `collections.deque([])` `        ``que.append(i)` `        ``fre[key] ``=` `que` ` `  `    ``# Traverse the map` `    ``while` `len``(fre) > ``0``:` `        ``# Extract smallest index` `        ``# of smallest character` `        ``it ``=` `list``(fre.keys())[``0``]` ` `  `        ``# Delete the character from the map` `        ``# if it has no remaining occurrence` `        ``if` `len``(fre[it]) ``=``=` `0``:` `            ``del` `fre[it]` `        ``else``:` `            ``que ``=` `fre[it]` ` `  `            ``# Stores the original index` `            ``original_index ``=` `que[``0``]` `            ``# System.out.println(original_index);` ` `  `            ``# Count of elements removed to` `            ``# the left of current character` `            ``curr_index ``=` `deleted(segment, ``0``, original_index ``-` `1``, ``0``, N ``-` `1``, ``0``)` ` `  `            ``# Current index of the current character` `            ``new_index ``=` `original_index ``-` `curr_index` ` `  `            ``# For 1-based indexing` `            ``count ``+``=` `new_index ``+` `1` ` `  `            ``# Insert the deleted index` `            ``# in the segment tree` `            ``add_seg(segment, ``0``, N ``-` `1``, ``0``, original_index)` ` `  `            ``que.popleft()` `            ``fre[it] ``=` `que` ` `  `    ``# Final answer` `    ``print``(count)`   `s ``=` `"geeksforgeeks"` `sumOfIndices(s)`   `# This code is contributed by mukesh07.`

## C#

 `// C# program to implement` `// the above approach` `using` `System;` `using` `System.Collections.Generic;` `using` `System.Linq;` `class` `GFG {` `   `  `    ``// Function to add index of the deleted character` `    ``static` `void` `add_seg(``int``[] seg, ``int` `start, ``int` `end,` `                        ``int` `current, ``int` `index)` `    ``{` `         `  `        ``// If index is beyond the range` `        ``if` `(index > end || index < start)` `            ``return``;` `     `  `        ``// Insert the index of the deleted` `        ``// character` `        ``if` `(start == end)` `        ``{` `            ``seg[current] = 1;` `            ``return``;` `        ``}` `        ``int` `mid = (start + end) / 2;` `     `  `        ``// Search over the subtrees to find the` `        ``// desired index` `        ``add_seg(seg, start, mid, 2 * current + 1, index);` `        ``add_seg(seg, mid + 1, end, 2 * current + 2, index);` `        ``seg[current] = seg[2 * current + 1] + seg[2 * current + 2];` `    ``}` `     `  `    ``// Function to return count of deleted indices` `    ``// which are to the left of the current index` `    ``static` `int` `deleted(``int``[] seg, ``int` `l, ``int` `r, ``int` `start, ``int` `end, ``int` `current)` `    ``{` `        ``if` `(end < l || start > r)` `            ``return` `0;` `        ``if` `(start >= l && end <= r)` `            ``return` `seg[current];` `             `  `        ``int` `mid = (start + end) / 2;` `         `  `        ``return` `deleted(seg, l, r, start, mid, 2 * current + 1) +` `               ``deleted(seg, l, r, mid + 1, end, 2 * current + 2);` `    ``}` `     `  `    ``// Function to generate the` `    ``// sum of indices` `    ``static` `void` `sumOfIndices(``string` `s)` `    ``{` `        ``int` `N = s.Length;` `        ``int` `x = (``int``)(Math.Ceiling(Math.Log(N) / Math.Log(2)));` `        ``int` `seg_size = 2 * (``int``)Math.Pow(2, x) - 1;` `        ``int``[] segment = ``new` `int``[seg_size];` `     `  `        ``int` `count = 4;` `     `  `        ``// Stores the original index of the` `        ``// characters in sorted order of key` `        ``Dictionary<``int``, List<``int``>> fre = ``new` `Dictionary<``int``, List<``int``>>();` `        ``for``(``int` `i = 0; i < N; i++)` `        ``{` `            ``int` `key = (``int``)(s[i]);` `            ``List<``int``> que = ``new` `List<``int``>();` `            ``if``(fre.ContainsKey(key))` `            ``{` `                ``que = fre[key];` `            ``}` `            ``que.Add(i);` `            ``fre[key] = que;` `        ``}` `     `  `        ``// Traverse the map` `        ``while` `(fre.Count > 0)` `        ``{` `             `  `            ``// Extract smallest index` `            ``// of smallest character` `            ``int` `it = fre.Keys.First();` `     `  `            ``// Delete the character from the map` `            ``// if it has no remaining occurrence` `            ``if` `(fre[it].Count == 0)` `                ``fre.Remove(it);` `            ``else` `            ``{` `                ``List<``int``> que = fre[it];` `     `  `                ``// Stores the original index` `                ``int` `original_index = que;` `                ``// System.out.println(original_index);` `     `  `                ``// Count of elements removed to` `                ``// the left of current character` `                ``int` `curr_index = deleted(segment, 0, original_index - 1, 0, N - 1, 0);` `     `  `                ``// Current index of the current character` `                ``int` `new_index = original_index - curr_index;` `     `  `                ``// For 1-based indexing` `                ``count += new_index + 1;` `     `  `                ``// Insert the deleted index` `                ``// in the segment tree` `                ``add_seg(segment, 0, N - 1, 0, original_index);` `     `  `                ``que.RemoveAt(0);` `                ``fre[it] = que;` `            ``}` `        ``}` `     `  `        ``// Final answer` `        ``Console.Write(count);` `    ``}` `  `  `  ``static` `void` `Main() {` `    ``string` `s = ``"geeksforgeeks"``;` `    ``sumOfIndices(s);` `  ``}` `}`   `// This code is contributed by divyeshrabadiya07.`

## Javascript

 ``

Output:

`41`

Time Complexity: O(N log N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Related Articles