Minimum cost to sort strings using reversal operations of different costs
Last Updated :
06 Nov, 2023
Given an array of strings and costs of reversing all strings, we need to sort the array. We cannot move strings in array, only string reversal is allowed. We need to reverse some of the strings in such a way that all strings make a lexicographic order and cost is also minimized. If it is not possible to sort strings in any way, output not possible.
Examples:
Input : arr[] = {?”, ?”, ?”},
reverseCost[] = {1, 3, 1}
Output : Minimum cost of sorting = 1
Explanation : We can make above string array sorted
by reversing one of 2nd or 3rd string, but reversing
2nd string cost 3, so we will reverse 3rd string to
make string array sorted with a cost 1 which is
minimum.
We can solve this problem using dynamic programming. We make a 2D array for storing the minimum cost of sorting.
dp[i][j] represents the minimum cost to make first i
strings sorted.
j = 1 means i'th string is reversed.
j = 0 means i'th string is not reversed.
Value of dp[i][j] is computed using dp[i-1][1] and
dp[i-1][0].
Computation of dp[i][0]
If arr[i] is greater than str[i-1], we update dp[i][0]
by dp[i-1][0]
If arr[i] is greater than reversal of previous string
we update dp[i][0] by dp[i-1][1]
Same procedure is applied to compute dp[i][1], we
reverse str[i] before applying the procedure.
At the end we will choose minimum of dp[N-1][0] and
dp[N-1][1] as our final answer if both of them not
updated yet even once, we will flag that sorting is
not possible.
Below is the implementation of above idea.
C++
#include <bits/stdc++.h>
using namespace std;
int minCost(string arr[], int cost[], int N)
{
int dp[N][2];
dp[0][0] = 0;
dp[0][1] = cost[0];
string revStr[N];
for ( int i = 0; i < N; i++)
{
revStr[i] = arr[i];
reverse(revStr[i].begin(), revStr[i].end());
}
string curStr;
int curCost;
for ( int i = 1; i < N; i++)
{
for ( int j = 0; j < 2; j++)
{
dp[i][j] = INT_MAX;
curStr = (j == 0) ? arr[i] : revStr[i];
curCost = (j == 0) ? 0 : cost[i];
if (curStr >= arr[i - 1])
dp[i][j] = min(dp[i][j], dp[i-1][0] + curCost);
if (curStr >= revStr[i - 1])
dp[i][j] = min(dp[i][j], dp[i-1][1] + curCost);
}
}
int res = min(dp[N-1][0], dp[N-1][1]);
return (res == INT_MAX)? -1 : res;
}
int main()
{
string arr[] = { "aa" , "ba" , "ac" };
int cost[] = {1, 3, 1};
int N = sizeof (arr) / sizeof (arr[0]);
int res = minCost(arr, cost, N);
if (res == -1)
cout << "Sorting not possible\n" ;
else
cout << "Minimum cost to sort strings is "
<< res;
}
|
Java
import java.util.*;
class GFG
{
static int minCost(String arr[], int cost[], int N)
{
int [][]dp = new int [N][ 2 ];
dp[ 0 ][ 0 ] = 0 ;
dp[ 0 ][ 1 ] = cost[ 0 ];
String []revStr = new String[N];
for ( int i = 0 ; i < N; i++)
{
revStr[i] = arr[i];
revStr[i] = reverse(revStr[i], 0 ,
revStr[i].length() - 1 );
}
String curStr = "" ;
int curCost;
for ( int i = 1 ; i < N; i++)
{
for ( int j = 0 ; j < 2 ; j++)
{
dp[i][j] = Integer.MAX_VALUE;
curStr = (j == 0 ) ? arr[i] : revStr[i];
curCost = (j == 0 ) ? 0 : cost[i];
if (curStr.compareTo(arr[i - 1 ]) >= 0 )
dp[i][j] = Math.min(dp[i][j],
dp[i - 1 ][ 0 ] + curCost);
if (curStr.compareTo(revStr[i - 1 ]) >= 0 )
dp[i][j] = Math.min(dp[i][j],
dp[i - 1 ][ 1 ] + curCost);
}
}
int res = Math.min(dp[N - 1 ][ 0 ], dp[N - 1 ][ 1 ]);
return (res == Integer.MAX_VALUE)? - 1 : res;
}
static String reverse(String s, int start, int end)
{
char temp;
char []str = s.toCharArray();
while (start <= end)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
return String.valueOf(str);
}
public static void main(String[] args)
{
String arr[] = { "aa" , "ba" , "ac" };
int cost[] = { 1 , 3 , 1 };
int N = arr.length;
int res = minCost(arr, cost, N);
if (res == - 1 )
System.out.println( "Sorting not possible\n" );
else
System.out.println( "Minimum cost to " +
"sort strings is " + res);
}
}
|
Python3
def ReverseStringMin(arr, reverseCost, n):
dp = [[ float ( "Inf" )] * 2 for i in range (n)]
dp[ 0 ][ 0 ] = 0
dp[ 0 ][ 1 ] = reverseCost[ 0 ]
rev_arr = [i[:: - 1 ] for i in arr]
for i in range ( 1 , n):
for j in range ( 2 ):
curStr = arr[i] if j = = 0 else rev_arr[i]
curCost = 0 if j = = 0 else reverseCost[i]
if (curStr > = arr[i - 1 ]):
dp[i][j] = min (dp[i][j], dp[i - 1 ][ 0 ] + curCost)
if (curStr > = rev_arr[i - 1 ]):
dp[i][j] = min (dp[i][j], dp[i - 1 ][ 1 ] + curCost)
res = min (dp[n - 1 ][ 0 ], dp[n - 1 ][ 1 ])
return res if res ! = float ( "Inf" ) else - 1
def main():
arr = [ "aa" , "ba" , "ac" ]
reverseCost = [ 1 , 3 , 1 ]
n = len (arr)
dp = [ float ( "Inf" )] * n
res = ReverseStringMin(arr, reverseCost,n)
if res ! = - 1 :
print ( "Minimum cost to sort sorting is" , res)
else :
print ( "Sorting not possible" )
if __name__ = = '__main__' :
main()
|
C#
using System;
class GFG
{
static int minCost(String []arr,
int []cost, int N)
{
int [,]dp = new int [N, 2];
dp[0, 0] = 0;
dp[0, 1] = cost[0];
String []revStr = new String[N];
for ( int i = 0; i < N; i++)
{
revStr[i] = arr[i];
revStr[i] = reverse(revStr[i], 0,
revStr[i].Length - 1);
}
String curStr = "" ;
int curCost;
for ( int i = 1; i < N; i++)
{
for ( int j = 0; j < 2; j++)
{
dp[i, j] = int .MaxValue;
curStr = (j == 0) ? arr[i] : revStr[i];
curCost = (j == 0) ? 0 : cost[i];
if (curStr.CompareTo(arr[i - 1]) >= 0)
dp[i, j] = Math.Min(dp[i, j],
dp[i - 1, 0] + curCost);
if (curStr.CompareTo(revStr[i - 1]) >= 0)
dp[i, j] = Math.Min(dp[i, j],
dp[i - 1, 1] + curCost);
}
}
int res = Math.Min(dp[N - 1, 0],
dp[N - 1, 1]);
return (res == int .MaxValue) ? -1 : res;
}
static String reverse(String s, int start, int end)
{
char temp;
char []str = s.ToCharArray();
while (start <= end)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
return String.Join( "" , str);
}
public static void Main(String[] args)
{
String []arr = { "aa" , "ba" , "ac" };
int []cost = {1, 3, 1};
int N = arr.Length;
int res = minCost(arr, cost, N);
if (res == -1)
Console.WriteLine( "Sorting not possible\n" );
else
Console.WriteLine( "Minimum cost to " +
"sort strings is " + res);
}
}
|
Javascript
<script>
function minCost(arr,cost,N)
{
let dp= new Array(N);
for (let i=0;i<N;i++)
{
dp[i]= new Array(2);
for (let j=0;j<2;j++)
{
dp[i][j]=0;
}
}
dp[0][0] = 0;
dp[0][1] = cost[0];
let revStr = new Array(N);
for (let i=0;i<N;i++)
{
revStr[i]= "" ;
}
for (let i = 0; i < N; i++)
{
revStr[i] = arr[i];
revStr[i] = reverse(revStr[i], 0,
revStr[i].length - 1);
}
let curStr = "" ;
let curCost;
for (let i = 1; i < N; i++)
{
for (let j = 0; j < 2; j++)
{
dp[i][j] = Number.MAX_VALUE;
curStr = (j == 0) ? arr[i] : revStr[i];
curCost = (j == 0) ? 0 : cost[i];
if (curStr>=arr[i - 1])
dp[i][j] = Math.min(dp[i][j],
dp[i - 1][0] + curCost);
if (curStr>=revStr[i - 1])
dp[i][j] = Math.min(dp[i][j],
dp[i - 1][1] + curCost);
}
}
let res = Math.min(dp[N - 1][0], dp[N - 1][1]);
return (res == Number.MAX_VALUE)? -1 : res;
}
function reverse(s,start,end)
{
let temp;
let str=s.split( "" );
while (start <= end)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
return str.toString();
}
let arr=[ "aa" , "ba" , "ac" ];
let cost=[1, 3, 1];
let N = arr.length;
let res = minCost(arr, cost, N);
if (res == -1)
document.write( "Sorting not possible\n" );
else
document.write( "Minimum cost to " +
"sort strings is " + res);
</script>
|
PHP
<?php
function minCost(& $arr , & $cost , $N )
{
$dp = array_fill (0, $N ,
array_fill (0, 2, NULL));
$dp [0][0] = 0;
$dp [0][1] = $cost [0];
$revStr = array_fill (false, $N , NULL);
for ( $i = 0; $i < $N ; $i ++)
{
$revStr [ $i ] = $arr [ $i ];
$revStr [ $i ] = strrev ( $revStr [ $i ]);
}
$curStr = "" ;
for ( $i = 1; $i < $N ; $i ++)
{
for ( $j = 0; $j < 2; $j ++)
{
$dp [ $i ][ $j ] = PHP_INT_MAX;
if ( $j == 0)
$curStr = $arr [ $i ];
else
$curStr = $revStr [ $i ];
if ( $j == 0)
$curCost = 0 ;
else
$curCost = $cost [ $i ];
if ( $curStr >= $arr [ $i - 1])
$dp [ $i ][ $j ] = min( $dp [ $i ][ $j ],
$dp [ $i - 1][0] +
$curCost );
if ( $curStr >= $revStr [ $i - 1])
$dp [ $i ][ $j ] = min( $dp [ $i ][ $j ],
$dp [ $i - 1][1] +
$curCost );
}
}
$res = min( $dp [ $N - 1][0], $dp [ $N - 1][1]);
if ( $res == PHP_INT_MAX)
return -1 ;
else
return $res ;
}
$arr = array ( "aa" , "ba" , "ac" );
$cost = array (1, 3, 1);
$N = sizeof( $arr );
$res = minCost( $arr , $cost , $N );
if ( $res == -1)
echo "Sorting not possible\n" ;
else
echo "Minimum cost to sort strings is " . $res ;
?>
|
Output
Minimum cost to sort strings is 1
Time Complexity: O(N)
Auxiliary Space: O(N)
Efficient approach : Space Optimization O(1)
To optimize the space complexity of the above approach, we can eliminate the need for a 2D array dp and instead use variables to store the previous minimum costs. This will reduce the space complexity from O(N) to O(1).
Implementations Steps:
- Initialize dp0 as 0 and dp1 as the cost of the first string.
- Iterate from i = 1 to N-1, where N is the number of strings.
- Inside the loop, initialize cur0 and cur1 as INT_MAX.
- Compare arr[i] with arr[i-1] and update cur0 if arr[i] is larger or equal.
- Compare reversed arr[i] with arr[i-1] and update cur1 if it is larger or equal.
- Update dp0 with cur0 and dp1 with cur1.
- Get the minimum cost from dp0 and dp1 at the last index.
- If the minimum cost is still INT_MAX, return -1; otherwise, return the minimum cost.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int minCost(string arr[], int cost[], int N)
{
int dp0 = 0;
int dp1 = cost[0];
for ( int i = 1; i < N; i++)
{
int cur0 = INT_MAX;
int cur1 = INT_MAX;
if (arr[i] >= arr[i - 1])
cur0 = min(cur0, dp0);
if (arr[i] >= string(arr[i - 1].rbegin(), arr[i - 1].rend()))
cur0 = min(cur0, dp1);
if (string(arr[i].rbegin(), arr[i].rend()) >= arr[i - 1])
cur1 = min(cur1, dp0 + cost[i]);
if (string(arr[i].rbegin(), arr[i].rend()) >= string(arr[i - 1].rbegin(), arr[i - 1].rend()))
cur1 = min(cur1, dp1 + cost[i]);
dp0 = cur0;
dp1 = cur1;
}
int res = min(dp0, dp1);
return (res == INT_MAX) ? -1 : res;
}
int main()
{
string arr[] = { "aa" , "ba" , "ac" };
int cost[] = {1, 3, 1};
int N = sizeof (arr) / sizeof (arr[0]);
int res = minCost(arr, cost, N);
if (res == -1)
cout << "Sorting not possible\n" ;
else
cout << "Minimum cost to sort strings is " << res;
return 0;
}
|
Java
import java.util.Arrays;
public class GFG {
public static int minCost(String[] arr, int [] cost, int N) {
int dp0 = 0 ;
int dp1 = cost[ 0 ];
for ( int i = 1 ; i < N; i++) {
int cur0 = Integer.MAX_VALUE;
int cur1 = Integer.MAX_VALUE;
if (arr[i].compareTo(arr[i - 1 ]) >= 0 )
cur0 = Math.min(cur0, dp0);
if (arr[i].compareTo( new StringBuilder(arr[i - 1 ]).reverse().toString()) >= 0 )
cur0 = Math.min(cur0, dp1);
if ( new StringBuilder(arr[i]).reverse().toString().compareTo(arr[i - 1 ]) >= 0 )
cur1 = Math.min(cur1, dp0 + cost[i]);
if ( new StringBuilder(arr[i]).reverse().toString().compareTo(
new StringBuilder(arr[i - 1 ]).reverse().toString()) >= 0 )
cur1 = Math.min(cur1, dp1 + cost[i]);
dp0 = cur0;
dp1 = cur1;
}
int res = Math.min(dp0, dp1);
return (res == Integer.MAX_VALUE) ? - 1 : res;
}
public static void main(String[] args) {
String[] arr = { "aa" , "ba" , "ac" };
int [] cost = { 1 , 3 , 1 };
int N = arr.length;
int res = minCost(arr, cost, N);
if (res == - 1 )
System.out.println( "Sorting not possible" );
else
System.out.println( "Minimum cost to sort strings is " + res);
}
}
|
Python3
def min_cost(arr, cost, N):
dp0 = 0
dp1 = cost[ 0 ]
for i in range ( 1 , N):
cur0 = float ( 'inf' )
cur1 = float ( 'inf' )
if arr[i] > = arr[i - 1 ]:
cur0 = min (cur0, dp0)
if arr[i] > = arr[i - 1 ][:: - 1 ]:
cur0 = min (cur0, dp1)
if arr[i][:: - 1 ] > = arr[i - 1 ]:
cur1 = min (cur1, dp0 + cost[i])
if arr[i][:: - 1 ] > = arr[i - 1 ][:: - 1 ]:
cur1 = min (cur1, dp1 + cost[i])
dp0 = cur0
dp1 = cur1
res = min (dp0, dp1)
return - 1 if res = = float ( 'inf' ) else res
arr = [ "aa" , "ba" , "ac" ]
cost = [ 1 , 3 , 1 ]
N = len (arr)
res = min_cost(arr, cost, N)
if res = = - 1 :
print ( "Sorting not possible" )
else :
print ( "Minimum cost to sort strings is" , res)
|
C#
using System;
using System.Linq;
class Program
{
static int MinCost( string [] arr, int [] cost, int N)
{
int dp0 = 0;
int dp1 = cost[0];
for ( int i = 1; i < N; i++)
{
int cur0 = int .MaxValue;
int cur1 = int .MaxValue;
if ( string .Compare(arr[i], arr[i - 1]) >= 0)
cur0 = Math.Min(cur0, dp0);
if ( string .Compare(arr[i], new string (arr[i - 1].Reverse().ToArray())) >= 0)
cur0 = Math.Min(cur0, dp1);
if ( string .Compare( new string (arr[i].Reverse().ToArray()), arr[i - 1]) >= 0)
cur1 = Math.Min(cur1, dp0 + cost[i]);
if ( string .Compare( new string (arr[i].Reverse().ToArray()), new string (arr[i - 1].Reverse().ToArray())) >= 0)
cur1 = Math.Min(cur1, dp1 + cost[i]);
dp0 = cur0;
dp1 = cur1;
}
int res = Math.Min(dp0, dp1);
return (res == int .MaxValue) ? -1 : res;
}
static void Main()
{
string [] arr = { "aa" , "ba" , "ac" };
int [] cost = { 1, 3, 1 };
int N = arr.Length;
int res = MinCost(arr, cost, N);
if (res == -1)
Console.WriteLine( "Sorting not possible" );
else
Console.WriteLine( "Minimum cost to sort strings is " + res);
}
}
|
Javascript
function minCost(arr, cost, N) {
let dp0 = 0;
let dp1 = cost[0];
for (let i = 1; i < N; i++) {
let cur0 = Number.POSITIVE_INFINITY;
let cur1 = Number.POSITIVE_INFINITY;
if (arr[i] >= arr[i - 1]) {
cur0 = Math.min(cur0, dp0);
}
if (arr[i] >= arr[i - 1].split( '' ).reverse().join( '' )) {
cur0 = Math.min(cur0, dp1);
}
if (arr[i].split( '' ).reverse().join( '' ) >= arr[i - 1]) {
cur1 = Math.min(cur1, dp0 + cost[i]);
}
if (arr[i].split( '' ).reverse().join( '' ) >= arr[i - 1].split( '' ).reverse().join( '' )) {
cur1 = Math.min(cur1, dp1 + cost[i]);
}
dp0 = cur0;
dp1 = cur1;
}
let res = Math.min(dp0, dp1);
if (res === Number.POSITIVE_INFINITY) {
return -1;
} else {
return res;
}
}
const arr = [ "aa" , "ba" , "ac" ];
const cost = [1, 3, 1];
const N = arr.length;
const res = minCost(arr, cost, N);
if (res === -1) {
console.log( "Sorting not possible" );
} else {
console.log( "Minimum cost to sort strings is" , res);
}
|
Output
Minimum cost to sort strings is 1
Time Complexity: O(N)
Auxiliary Space: O(1)
This article is contributed by Utkarsh Trivedi.
Share your thoughts in the comments
Please Login to comment...