Minimum replacements to make adjacent characters unequal in a ternary string | Set-2
Last Updated :
25 Oct, 2023
Given a string of ‘0’, ‘1’, and ‘2’. The task is to find the minimum number of replacements such that the adjacent characters are not equal.
Examples:
Input: s = “201220211”
Output: 2
Resultant string after changes is 201210210
Input: s = “0120102”
Output: 0
Approach:
The problem has been solved using a greedy approach in the previous post. In this post, we will discuss a Dynamic Programming approach to solve the same problem. Create a function charVal which returns 0, 1, or 2 depending on the character.
A recursive function is made which calls the charVal function to get the i-th value, and if this is equal to the previous one, then only the other two states (1 or 2, 0 or 1, 0 or 2) are used at i-th character. If it is not equal to the previous one, no changes are made. A dp[][] array is used for memoization. The base case is when all the positions are filled. If any of the states is re-visited, then return the value that is stored in the dp[][] array. DP[i][j] means that i-th position is filled with j-th character.
Below is the implementation of the above problem:
C++
#include <bits/stdc++.h>
using namespace std;
int charVal(string s, int i)
{
if (s[i] == '0' )
return 0;
else if (s[i] == '1' )
return 1;
else
return 2;
}
int countMinimalReplacements(string s, int i,
int prev, int dp[][3], int n)
{
if (i == n) {
return 0;
}
if (dp[i][prev] != -1)
return dp[i][prev];
int val = charVal(s, i);
int ans = INT_MAX;
if (val == prev) {
int val = 0;
for ( int cur = 0; cur <= 2; cur++) {
if (cur == prev)
continue ;
val = 1 + countMinimalReplacements(s, i + 1, cur, dp, n);
ans = min(ans, val);
}
}
else
ans = countMinimalReplacements(s, i + 1, val, dp, n);
return dp[i][val] = ans;
}
int main()
{
string s = "201220211" ;
int n = s.length();
int dp[n][3];
memset (dp, -1, sizeof dp);
int val = charVal(s, 0);
cout << countMinimalReplacements(s, 1, val, dp, n);
return 0;
}
|
Java
class GFG
{
static int charVal(String s, int i)
{
if (s.charAt(i) == '0' )
{
return 0 ;
}
else if (s.charAt(i) == '1' )
{
return 1 ;
}
else
{
return 2 ;
}
}
static int countMinimalReplacements(String s, int i,
int prev, int dp[][], int n)
{
if (i == n)
{
return 0 ;
}
if (dp[i][prev] != - 1 )
{
return dp[i][prev];
}
int val = charVal(s, i);
int ans = Integer.MAX_VALUE;
if (val == prev)
{
val = 0 ;
for ( int cur = 0 ; cur <= 2 ; cur++)
{
if (cur == prev)
{
continue ;
}
val = 1 + countMinimalReplacements(s,
i + 1 , cur, dp, n);
ans = Math.min(ans, val);
}
} else
{
ans = countMinimalReplacements(s, i + 1 ,
val, dp, n);
}
return dp[i][val] = ans;
}
public static void main(String[] args)
{
String s = "201220211" ;
int n = s.length();
int dp[][] = new int [n][ 3 ];
for ( int i = 0 ; i < n; i++)
{
for ( int j = 0 ; j < 3 ; j++)
{
dp[i][j] = - 1 ;
}
}
int val = charVal(s, 0 );
System.out.println(countMinimalReplacements(s, 1 ,
val, dp, n));
}
}
|
Python3
import sys
def charVal(s, i):
if (s[i] = = '0' ):
return 0
elif (s[i] = = '1' ):
return 1
else :
return 2
def countMinimalReplacements(s,i,prev, dp, n):
if (i = = n):
return 0
if (dp[i][prev] ! = - 1 ):
return dp[i][prev]
val = charVal(s, i)
ans = sys.maxsize
if (val = = prev):
val = 0
for cur in range ( 3 ):
if (cur = = prev):
continue
val = 1 + countMinimalReplacements(s, i + 1 , cur, dp, n)
ans = min (ans, val)
else :
ans = countMinimalReplacements(s, i + 1 , val, dp, n)
dp[i][val] = ans
return dp[i][val]
if __name__ = = '__main__' :
s = "201220211"
n = len (s)
dp = [[ - 1 for i in range ( 3 )] for i in range (n)]
val = charVal(s, 0 )
print (countMinimalReplacements(s, 1 , val, dp, n))
|
C#
using System;
class GFG
{
static int charVal( string s, int i)
{
if (s[i] == '0' )
{
return 0;
}
else if (s[i] == '1' )
{
return 1;
}
else
{
return 2;
}
}
static int countMinimalReplacements( string s, int i,
int prev, int [,]dp, int n)
{
if (i == n)
{
return 0;
}
if (dp[i,prev] != -1)
{
return dp[i,prev];
}
int val = charVal(s, i);
int ans = int .MaxValue;
if (val == prev)
{
val = 0;
for ( int cur = 0; cur <= 2; cur++)
{
if (cur == prev)
{
continue ;
}
val = 1 + countMinimalReplacements(s,
i + 1, cur, dp, n);
ans = Math.Min(ans, val);
}
}
else
{
ans = countMinimalReplacements(s, i + 1,
val, dp, n);
}
return dp[i,val] = ans;
}
public static void Main()
{
string s = "201220211" ;
int n = s.Length;
int [,]dp = new int [n,3];
for ( int i = 0; i < n; i++)
{
for ( int j = 0; j < 3; j++)
{
dp[i,j] = -1;
}
}
int val = charVal(s, 0);
Console.WriteLine(countMinimalReplacements(s, 1,
val, dp, n));
}
}
|
Javascript
<script>
function charVal( s , i) {
if (s.charAt(i) == '0' ) {
return 0;
} else if (s.charAt(i) == '1' ) {
return 1;
} else {
return 2;
}
}
function countMinimalReplacements( s , i , prev , dp , n)
{
if (i == n) {
return 0;
}
if (dp[i][prev] != -1) {
return dp[i][prev];
}
var val = charVal(s, i);
var ans = Number.MAX_VALUE;
if (val == prev) {
val = 0;
for ( var cur = 0; cur <= 2; cur++) {
if (cur == prev) {
continue ;
}
val = 1 +
countMinimalReplacements(s, i + 1, cur, dp, n);
ans = Math.min(ans, val);
}
} else
{
ans =
countMinimalReplacements(s, i + 1, val, dp, n);
}
return dp[i][val] = ans;
}
var s = "201220211" ;
var n = s.length;
var dp = Array(n).fill().map(()=>Array(3).fill(0));
for ( var i = 0; i < n; i++) {
for ( var j = 0; j < 3; j++) {
dp[i][j] = -1;
}
}
var val = charVal(s, 0);
document.write(countMinimalReplacements(s, 1, val, dp, n));
</script>
|
Complexity Analysis:
- Time Complexity: O(3*N), as we are using recursion with memoization will cost us O(N) time as we will avoid unnecessary recursive calls. Where N is the number of characters in the string.
- Auxiliary Space: O(3*N), as we are using extra space for the DP matrix. Where N is the number of characters in the string.
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a DP to store the solution of the subproblems and initialize it with 0.
- Initialize the DP with base cases dp[0][val] = 0.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
- Create variable ans to store final result and initialize it with INT_MAX.
- Now iterate over DP and update ans.
- At last return and print ans.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int charVal(string s, int i)
{
if (s[i] == '0' )
return 0;
else if (s[i] == '1' )
return 1;
else
return 2;
}
int countMinimalReplacements(string s, int n)
{
int dp[n][3];
memset (dp, -1, sizeof dp);
int val = charVal(s, 0);
dp[0][val] = 0;
for ( int i = 1; i < n; i++) {
int curVal = charVal(s, i);
for ( int prev = 0; prev <= 2; prev++) {
if (dp[i-1][prev] == -1) continue ;
if (curVal == prev) {
for ( int cur = 0; cur <= 2; cur++) {
if (cur == prev) continue ;
int newVal = dp[i-1][prev] + 1;
if (dp[i][cur] == -1 || newVal < dp[i][cur]) {
dp[i][cur] = newVal;
}
}
} else {
int newVal = dp[i-1][prev];
if (dp[i][curVal] == -1 || newVal < dp[i][curVal]) {
dp[i][curVal] = newVal;
}
}
}
}
int ans = INT_MAX;
for ( int cur = 0; cur <= 2; cur++) {
if (dp[n-1][cur] == -1) continue ;
ans = min(ans, dp[n-1][cur]);
}
return ans;
}
int main()
{
string s = "201220211" ;
int n = s.length();
cout << countMinimalReplacements(s, n) << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class MinimalReplacements {
static int charVal(String s, int i) {
if (s.charAt(i) == '0' )
return 0 ;
else if (s.charAt(i) == '1' )
return 1 ;
else
return 2 ;
}
static int countMinimalReplacements(String s, int n) {
int [][] dp = new int [n][ 3 ];
for ( int i = 0 ; i < n; i++) {
Arrays.fill(dp[i], - 1 );
}
int val = charVal(s, 0 );
dp[ 0 ][val] = 0 ;
for ( int i = 1 ; i < n; i++) {
int curVal = charVal(s, i);
for ( int prev = 0 ; prev <= 2 ; prev++) {
if (dp[i- 1 ][prev] == - 1 ) continue ;
if (curVal == prev) {
for ( int cur = 0 ; cur <= 2 ; cur++) {
if (cur == prev) continue ;
int newVal = dp[i- 1 ][prev] + 1 ;
if (dp[i][cur] == - 1 || newVal < dp[i][cur]) {
dp[i][cur] = newVal;
}
}
} else {
int newVal = dp[i- 1 ][prev];
if (dp[i][curVal] == - 1 || newVal < dp[i][curVal]) {
dp[i][curVal] = newVal;
}
}
}
}
int ans = Integer.MAX_VALUE;
for ( int cur = 0 ; cur <= 2 ; cur++) {
if (dp[n- 1 ][cur] == - 1 ) continue ;
ans = Math.min(ans, dp[n- 1 ][cur]);
}
return ans;
}
public static void main(String[] args) {
String s = "201220211" ;
int n = s.length();
System.out.println(countMinimalReplacements(s, n));
}
}
|
Python
import sys
def charVal(s, i):
if (s[i] = = '0' ):
return 0
elif (s[i] = = '1' ):
return 1
else :
return 2
def countMinimalReplacements(s, n):
dp = [[ - 1 for i in range ( 3 )] for j in range (n)]
val = charVal(s, 0 )
dp[ 0 ][val] = 0
for i in range ( 1 , n):
curVal = charVal(s, i)
for prev in range ( 0 , 3 ):
if (dp[i - 1 ][prev] = = - 1 ): continue
if (curVal = = prev):
for cur in range ( 0 , 3 ):
if (cur = = prev): continue
newVal = dp[i - 1 ][prev] + 1
if (dp[i][cur] = = - 1 or newVal < dp[i][cur]):
dp[i][cur] = newVal
else :
newVal = dp[i - 1 ][prev]
if (dp[i][curVal] = = - 1 or newVal < dp[i][curVal]):
dp[i][curVal] = newVal
ans = sys.maxsize
for cur in range ( 0 , 3 ):
if (dp[n - 1 ][cur] = = - 1 ): continue
ans = min (ans, dp[n - 1 ][cur])
return ans
if __name__ = = '__main__' :
s = "201220211"
n = len (s)
print (countMinimalReplacements(s, n))
|
C#
using System;
class Program
{
static int CharVal( string s, int i)
{
if (s[i] == '0' )
return 0;
else if (s[i] == '1' )
return 1;
else
return 2;
}
static int CountMinimalReplacements( string s, int n)
{
int [][] dp = new int [n][];
for ( int i = 0; i < n; i++)
{
dp[i] = new int [3];
for ( int j = 0; j < 3; j++)
{
dp[i][j] = -1;
}
}
int val = CharVal(s, 0);
dp[0][val] = 0;
for ( int i = 1; i < n; i++)
{
int curVal = CharVal(s, i);
for ( int prev = 0; prev < 3; prev++)
{
if (dp[i - 1][prev] == -1) continue ;
if (curVal == prev)
{
for ( int cur = 0; cur < 3; cur++)
{
if (cur == prev) continue ;
int newVal = dp[i - 1][prev] + 1;
if (dp[i][cur] == -1 || newVal < dp[i][cur])
{
dp[i][cur] = newVal;
}
}
}
else
{
int newVal = dp[i - 1][prev];
if (dp[i][curVal] == -1 || newVal < dp[i][curVal])
{
dp[i][curVal] = newVal;
}
}
}
}
int ans = int .MaxValue;
for ( int cur = 0; cur < 3; cur++)
{
if (dp[n - 1][cur] == -1) continue ;
ans = Math.Min(ans, dp[n - 1][cur]);
}
return ans;
}
static void Main()
{
string s = "201220211" ;
int n = s.Length;
Console.WriteLine(CountMinimalReplacements(s, n));
}
}
|
Javascript
function charVal(s, i) {
if (s[i] === '0' ) {
return 0;
} else if (s[i] === '1' ) {
return 1;
} else {
return 2;
}
}
function countMinimalReplacements(s) {
const n = s.length;
const dp = new Array(n);
for (let i = 0; i < n; i++) {
dp[i] = new Array(3).fill(-1);
}
const val = charVal(s, 0);
dp[0][val] = 0;
for (let i = 1; i < n; i++) {
const curVal = charVal(s, i);
for (let prev = 0; prev <= 2; prev++) {
if (dp[i-1][prev] === -1) continue ;
if (curVal === prev) {
for (let cur = 0; cur <= 2; cur++) {
if (cur === prev) continue ;
const newVal = dp[i-1][prev] + 1;
if (dp[i][cur] === -1 || newVal < dp[i][cur]) {
dp[i][cur] = newVal;
}
}
} else {
const newVal = dp[i-1][prev];
if (dp[i][curVal] === -1 || newVal < dp[i][curVal]) {
dp[i][curVal] = newVal;
}
}
}
}
let ans = Infinity;
for (let cur = 0; cur <= 2; cur++) {
if (dp[n-1][cur] === -1) continue ;
ans = Math.min(ans, dp[n-1][cur]);
}
return ans;
}
const s = "201220211" ;
const n = s.length;
console.log(countMinimalReplacements(s));
|
Output:
2
Time Complexity: O(3*N)
Auxiliary Space: O(3*N)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...