Minimize cost of removals required to make all remaining characters of the string unique
Given a string str and an array cost[] of size N where cost[i] denotes the cost to remove the ith character from the string str, the task is to find the minimum cost of removals required to make every character of the string unique.
Examples:
Input: str = “AAABBB”, cost = {1, 2, 3, 4, 5, 6}
Output: 12
Explanation: Removing characters at indices 0, 1, 3, 4 modifies str to “AB”. Therefore, the total cost of removals = 1 + 2 + 4 + 5 = 12
Input: str = “geeksforgeeks”, cost = {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1, 2, 3}
Output: 10
Explanation: Removing characters at indices 0, 1, 9, 10, 11, 12 modifies str to “eksforg”. Therefore, the total cost of removals = 1 + 2 + 1 + 1 + 2 + 3 = 10
Naive Approach: The simplest approach to solve the problem is to traverse the string and for every character, traverse the remaining characters and find its occurrences. Store the maximum cost of removing an occurrence. Add the cost of removing all other occurrences of the character to the sum. Finally, after completing this for all the characters of the string, print the final sum obtained.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int delCost(string s, int cost[], int l1, int l2)
{
bool visited[l1];
memset (visited, 0, sizeof (visited));
int ans = 0;
for ( int i = 0; i < l1; i++)
{
if (visited[i])
{
continue ;
}
int maxDel = 0;
int totalCost = 0;
visited[i] = 1;
for ( int j = i; j < l1; j++)
{
if (s[i] == s[j])
{
maxDel = max(maxDel, cost[j]);
totalCost += cost[j];
visited[j] = 1;
}
}
ans += totalCost - maxDel;
}
return ans;
}
int main()
{
string s = "AAABBB" ;
int l1 = s.size();
int cost[] = { 1, 2, 3, 4, 5, 6 };
int l2 = sizeof (cost) / sizeof (cost[0]);
cout << delCost(s, cost, l1, l2);
return 0;
}
|
Java
import java.io.*;
class GFG
{
public static int delCost(String s, int [] cost)
{
boolean visited[] = new boolean [s.length()];
int ans = 0 ;
for ( int i = 0 ; i < s.length(); i++)
{
if (visited[i])
{
continue ;
}
int maxDel = 0 ;
int totalCost = 0 ;
visited[i] = true ;
for ( int j = i; j < s.length(); j++)
{
if (s.charAt(i) == s.charAt(j))
{
maxDel = Math.max(maxDel, cost[j]);
totalCost += cost[j];
visited[j] = true ;
}
}
ans += totalCost - maxDel;
}
return ans;
}
public static void main(String[] args)
{
String s = "AAABBB" ;
int [] cost = { 1 , 2 , 3 , 4 , 5 , 6 };
System.out.println(delCost(s, cost));
}
}
|
Python3
def delCost(s, cost):
visited = [ False ] * len (s)
ans = 0
for i in range ( len (s)):
if visited[i]:
continue
maxDel = 0
totCost = 0
visited[i] = True
for j in range (i, len (s)):
if s[i] = = s[j]:
maxDel = max (maxDel, cost[j])
totCost + = cost[j]
visited[j] = True
ans + = totCost - maxDel
return ans
string = "AAABBB"
cost = [ 1 , 2 , 3 , 4 , 5 , 6 ]
print (delCost(string, cost))
|
C#
using System;
using System.Collections.Generic;
class GFG{
public static int delCost( string s, int [] cost)
{
bool [] visited = new bool [s.Length];
int ans = 0;
for ( int i = 0; i < s.Length; i++)
{
if (visited[i] != false )
{
continue ;
}
int maxDel = 0;
int totalCost = 0;
visited[i] = true ;
for ( int j = i; j < s.Length; j++)
{
if (s[i] == s[j])
{
maxDel = Math.Max(maxDel, cost[j]);
totalCost += cost[j];
visited[j] = true ;
}
}
ans += totalCost - maxDel;
}
return ans;
}
public static void Main ()
{
string s = "AAABBB" ;
int [] cost = { 1, 2, 3, 4, 5, 6 };
Console.Write(delCost(s, cost));
}
}
|
Javascript
<script>
function delCost( s, cost) {
var visited =Array(s.length).fill( false );
var ans = 0;
for (i = 0; i < s.length; i++) {
if (visited[i]) {
continue ;
}
var maxDel = 0;
var totalCost = 0;
visited[i] = true ;
for (j = i; j < s.length; j++) {
if (s.charAt(i) == s.charAt(j)) {
maxDel = Math.max(maxDel, cost[j]);
totalCost += cost[j];
visited[j] = true ;
}
}
ans += totalCost - maxDel;
}
return ans;
}
var s = "AAABBB" ;
var cost = [ 1, 2, 3, 4, 5, 6 ];
document.write(delCost(s, cost));
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is use Hashmap. Follow the steps below to solve the problem:
- Initialize a variable, say ans, to store the minimum cost required.
- Initialize two Hashmaps, say forMax and forTot, to store the maximum and total removal cost of each character respectively.
- Traverse the string S using the variable i.
- Update forMax[s[i]] = max(forMax(s[i]), cost[i]).
- Update forTot[s[i]] += cost[i].
- Traverse the Hashmap forMax
- For each character, keep the maximum cost character and delete its other duplicates by updating ans += forTot[i]-forMax[i].
- Print ans.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int delCost(string s, int cost[])
{
int ans = 0;
map< char , int > forMax;
map< char , int > forTot;
for ( int i = 0; i < s.length(); i++) {
if (!forMax[s[i]]) {
forMax[s[i]] = cost[i];
}
else {
forMax[s[i]] = max(cost[i], forMax[s[i]]);
}
if (!forTot[s[i]]) {
forTot[s[i]] = cost[i];
}
else {
forTot[s[i]] = forTot[s[i]] + cost[i];
}
}
for ( auto i : forMax) {
ans += forTot[i.first] - i.second;
}
return ans;
}
int main()
{
string s = "AAABBB" ;
int cost[] = { 1, 2, 3, 4, 5, 6 };
cout << (delCost(s, cost));
}
|
Java
import java.util.*;
public class GFG
{
static int delCost(String s, int [] cost)
{
int ans = 0 ;
HashMap<Character, Integer> forMax = new HashMap<>();
HashMap<Character, Integer> forTot = new HashMap<>();
for ( int i = 0 ; i < s.length(); i++)
{
if (!forMax.containsKey(s.charAt(i)))
{
forMax.put(s.charAt(i), cost[i]);
}
else
{
forMax.put(s.charAt(i), Math.max(cost[i], forMax.get(s.charAt(i))));
}
if (!forTot.containsKey(s.charAt(i)))
{
forTot.put(s.charAt(i), cost[i]);
}
else
{
forTot.put(s.charAt(i), forTot.get(s.charAt(i)) + cost[i]);
}
}
for (Map.Entry<Character, Integer> i : forMax.entrySet())
{
ans += forTot.get(i.getKey()) - i.getValue();
}
return ans;
}
public static void main(String[] args)
{
String s = "AAABBB" ;
int [] cost = { 1 , 2 , 3 , 4 , 5 , 6 };
System.out.println(delCost(s, cost));
}
}
|
Python3
def delCost(s, cost):
ans = 0
forMax = {}
forTot = {}
for i in range ( len (s)):
if s[i] not in forMax:
forMax[s[i]] = cost[i]
else :
forMax[s[i]] = max (cost[i], forMax[s[i]])
if s[i] not in forTot:
forTot[s[i]] = cost[i]
else :
forTot[s[i]] + = cost[i]
for i in forMax:
ans + = forTot[i] - forMax[i]
return ans
string = "AAABBB"
cost = [ 1 , 2 , 3 , 4 , 5 , 6 ]
print (delCost(string, cost))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int delCost( string s, int [] cost)
{
int ans = 0;
Dictionary< int , int > forMax = new Dictionary< int , int >();
Dictionary< int , int > forTot = new Dictionary< int , int >();
for ( int i = 0; i < s.Length; i++)
{
if (!forMax.ContainsKey(s[i]))
{
forMax[s[i]] = cost[i];
}
else
{
forMax[s[i]] = Math.Max(cost[i], forMax[s[i]]);
}
if (!forTot.ContainsKey(s[i]))
{
forTot[s[i]] = cost[i];
}
else
{
forTot[s[i]] += cost[i];
}
}
foreach (KeyValuePair< int , int > i in forMax)
{
ans += forTot[i.Key] - i.Value;
}
return ans;
}
static void Main()
{
string s = "AAABBB" ;
int [] cost = {1, 2, 3, 4, 5, 6};
Console.WriteLine(delCost(s, cost));
}
}
|
Javascript
<script>
function delCost(s, cost)
{
var ans = 0;
var forMax = new Map();
var forTot = new Map();
for ( var i = 0; i < s.length; i++) {
if (!forMax.has(s[i])) {
forMax.set(s[i], cost[i]);
}
else {
forMax.set(s[i], Math.max(forMax.get(s[i]),cost[i]))
}
if (!forTot.has(s[i])) {
forTot.set(s[i], cost[i]);
}
else {
forTot.set(s[i], forTot.get(s[i]) + cost[i])
}
}
forMax.forEach((value, key) => {
ans += forTot.get(key) - value;
});
return ans;
}
var s = "AAABBB" ;
var cost = [1, 2, 3, 4, 5, 6];
document.write(delCost(s, cost));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Last Updated :
27 Jul, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...