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

• Difficulty Level : Medium
• Last Updated : 20 Oct, 2021

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:

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.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

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``    ``// characeter``    ``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``    ``// characeter``    ``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``    ``# characeter``    ``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``        ``// characeter``        ``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