Minimum replacements to make adjacent characters unequal in a ternary string | Set-2

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) is 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 state is re-visited, then return the value that is stored in 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to count the minimal
// replacements such that adjacent characters
// are unequal
#include <bits/stdc++.h>
using namespace std;
  
// function to return integer value
// of i-th character in the string
int charVal(string s, int i)
{
    if (s[i] == '0')
        return 0;
    else if (s[i] == '1')
        return 1;
    else
        return 2;
}
  
// Function to count the number of
// minimal replacements
int countMinimalReplacements(string s, int i, 
                        int prev, int dp[][3], int n)
{
  
    // If the string has reached the end
    if (i == n) {
        return 0;
    }
  
    // If the state has been visited previously
    if (dp[i][prev] != -1)
        return dp[i][prev];
  
    // Get the curret value of character
    int val = charVal(s, i);
    int ans = INT_MAX;
  
    // If it is equal then change it
    if (val == prev) {
        int val = 0;
  
        // All possible changes
        for (int cur = 0; cur <= 2; cur++) {
            if (cur == prev)
                continue;
  
            // Change done
            val = 1 + countMinimalReplacements(s, i + 1, cur, dp, n);
  
            ans = min(ans, val);
        }
    }
    else // If same no change
        ans = countMinimalReplacements(s, i + 1, val, dp, n);
  
    return dp[i][val] = ans;
}
  
// Driver Code
int main()
{
    string s = "201220211";
  
    // Length of string
    int n = s.length();
  
    // Create a DP array
    int dp[n][3];
  
    memset(dp, -1, sizeof dp);
  
    // First character
    int val = charVal(s, 0);
  
    // Function to find minimal replacements
    cout << countMinimalReplacements(s, 1, val, dp, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to count the minimal
// replacements such that adjacent characters
// are unequal
class GFG 
{
  
    // function to return integer value
    // of i-th character in the string
    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;
        }
    }
  
    // Function to count the number of
    // minimal replacements
    static int countMinimalReplacements(String s, int i,
                            int prev, int dp[][], int n) 
    {
  
        // If the string has reached the end
        if (i == n) 
        {
            return 0;
        }
  
        // If the state has been visited previously
        if (dp[i][prev] != -1
        {
            return dp[i][prev];
        }
  
        // Get the curret value of character
        int val = charVal(s, i);
        int ans = Integer.MAX_VALUE;
  
        // If it is equal then change it
        if (val == prev)
        {
            val = 0;
  
            // All possible changes
            for (int cur = 0; cur <= 2; cur++) 
            {
                if (cur == prev) 
                {
                    continue;
                }
  
                // Change done
                val = 1 + countMinimalReplacements(s,
                                    i + 1, cur, dp, n);
  
                ans = Math.min(ans, val);
            }
        } else // If same no change
        {
            ans = countMinimalReplacements(s, i + 1,
                                        val, dp, n);
        }
  
        return dp[i][val] = ans;
    }
  
    // Driver Code
    public static void main(String[] args) 
    {
        String s = "201220211";
  
        // Length of string
        int n = s.length();
  
        // Create a DP array
        int dp[][] = new int[n][3];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                dp[i][j] = -1;
            }
        }
  
        // First character
        int val = charVal(s, 0);
  
        // Function to find minimal replacements
        System.out.println(countMinimalReplacements(s, 1,
                                            val, dp, n));
    }
  
// This code is contributed by PrinciRaj1992

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 program to count the minimal
# replacements such that adjacent characters
# are unequal
import sys
  
# function to return integer value
# of i-th character in the string
def charVal(s, i):
    if (s[i] == '0'):
        return 0
    elif (s[i] == '1'):
        return 1
    else:
        return 2
  
# Function to count the number of
# minimal replacements
def countMinimalReplacements(s,i,prev, dp, n):
      
    # If the string has reached the end
    if (i == n):
        return 0
  
    # If the state has been visited previously
    if (dp[i][prev] != -1):
        return dp[i][prev]
  
    # Get the curret value of character
    val = charVal(s, i)
    ans = sys.maxsize
  
    # If it is equal then change it
    if (val == prev):
        val = 0
  
        # All possible changes
        for cur in range(3):
            if (cur == prev):
                continue
  
            # Change done
            val = 1 + countMinimalReplacements(s, i + 1, cur, dp, n)
            ans = min(ans, val)
              
        # If same no change 
    else:
        ans = countMinimalReplacements(s, i + 1, val, dp, n)
  
    dp[i][val] = ans
  
    return dp[i][val]
  
# Driver Code
if __name__ == '__main__':
    s = "201220211"
  
    # Length of string
    n = len(s)
  
    # Create a DP array
    dp = [[-1 for i in range(3)] for i in range(n)]
  
    # First character
    val = charVal(s, 0)
  
    # Function to find minimal replacements
    print(countMinimalReplacements(s, 1, val, dp, n))
      
# This code is contributed by
# Surendra_Gangwar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to count the minimal 
// replacements such that adjacent 
// characters are unequal
using System;
  
class GFG 
  
    // function to return integer value 
    // of i-th character in the string 
    static int charVal(string s, int i) 
    
        if (s[i] == '0'
        
            return 0; 
        
        else if (s[i] == '1'
        
            return 1; 
        
        else
        
            return 2; 
        
    
  
    // Function to count the number of 
    // minimal replacements 
    static int countMinimalReplacements(string s, int i, 
                            int prev, int [,]dp, int n) 
    
  
        // If the string has reached the end 
        if (i == n) 
        
            return 0; 
        
  
        // If the state has been visited previously 
        if (dp[i,prev] != -1) 
        
            return dp[i,prev]; 
        
  
        // Get the curret value of character 
        int val = charVal(s, i); 
        int ans = int.MaxValue; 
  
        // If it is equal then change it 
        if (val == prev) 
        
            val = 0; 
  
            // All possible changes 
            for (int cur = 0; cur <= 2; cur++) 
            
                if (cur == prev) 
                
                    continue
                
  
                // Change done 
                val = 1 + countMinimalReplacements(s, 
                                    i + 1, cur, dp, n); 
  
                ans = Math.Min(ans, val); 
            
        
        else // If same no change 
        
            ans = countMinimalReplacements(s, i + 1, 
                                        val, dp, n); 
        
  
        return dp[i,val] = ans; 
    
  
    // Driver Code 
    public static void Main() 
    
        string s = "201220211"
  
        // Length of string 
        int n = s.Length; 
  
        // Create a DP array 
        int [,]dp = new int[n,3]; 
        for (int i = 0; i < n; i++) 
        
            for (int j = 0; j < 3; j++) 
            
                dp[i,j] = -1; 
            
        
  
        // First character 
        int val = charVal(s, 0); 
  
        // Function to find minimal replacements 
        Console.WriteLine(countMinimalReplacements(s, 1, 
                                            val, dp, n)); 
    }
  
// This code is contributed by Ryuga

chevron_right


Output:

2


My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.