Open In App

Minimize adjacent character differences in palindromic string with ‘?’

Given a string S. The string can contain small case English letters or ‘?’. You can replace ‘?’ with any small English letter. Now if it is possible to make the string S a palindrome after replacing all ‘?’ then find the palindromic string with a minimum sum of differences of adjacent characters. Otherwise, return -1.

Input: S = a???c??c????
Output: 4
Explanation: We can see that we can make the string palindrome. Now to get minimum sum we should replace all the ‘?’ between ‘a’ and ‘c’ with ‘b’ and all the ‘?’ between two ‘c’ with ‘c’. So after replacing all the ‘?’ the string:  abbbccccbbba. The sum of differences of adjacent characters is 4.



Input: S = a???c??c???c
Output: -1
Explanation: It is not possible to make the string palindrome.

Approach: To solve the  problem follow the below idea:



The idea is to iterate over the string from both ends, replace any ‘?’ character with the corresponding character from the other end if it is non ? character, and return -1 if it is not possible to make the string a palindrome. Calculate the minimum sum of differences of adjacent characters by iterating over the remaining characters in the first half of the string and multiplying the result by 2.

Below are the steps for the above approach:

Below is the code for the above approach:




// C++ code for the above approach:
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
 
int minimumSum(string s)
{
    int i, j, n, len_s, diff, ans = 0;
    char last = '\0';
 
    len_s = s.length();
 
    // Iterate over the string s from both
    // ends simultaneously
    for (i = 0, j = len_s - 1; i < j; i++, j--) {
 
        // If characters at current
        // positions match, continue
        if (s[i] == s[j]) {
            continue;
        }
 
        // If one character is '?' and the
        // other isn't, replace the '?'
        // with the other character
        else if (s[i] == '?' && s[j] != '?') {
            s[i] = s[j];
        }
        else if (s[i] != '?' && s[j] == '?') {
            s[j] = s[i];
        }
 
        // If neither character is '?',
        // it's not possible to make the
        // string palindromic, so return -1
        else {
            return -1;
        }
    }
 
    // Calculate the number of
    // characters to consider
    n = len_s / 2;
    if (len_s % 2 == 1) {
        n++;
    }
 
    // Find the first non-'?' character in
    // the first half of the string
    for (i = 0; i < n; i++) {
        if (s[i] != '?') {
            last = s[i];
            break;
        }
    }
 
    // Iterate over the remaining characters
    // and calculate the minimum sum of
    // absolute differences between
    // adjacent characters
    for (i = i + 1; i < n; i++) {
        if (s[i] == '?') {
            continue;
        }
        diff = abs(s[i] - last);
        ans += diff;
        last = s[i];
    }
 
    // Multiply the minimum sum by
    // 2 and return it
    return 2 * ans;
}
 
// Drivers code
int main()
{
    string s = "a???c??c????";
 
    // Function call
    cout << minimumSum(s) << endl;
    return 0;
}




import java.lang.Math;
 
public class Main {
    public static int minimumSum(String s)
    {
        int i, j, n, len_s, diff, ans = 0;
        char last = '\0';
 
        len_s = s.length();
 
        // Iterate over the string s from both ends
        // simultaneously
        for (i = 0, j = len_s - 1; i < j; i++, j--) {
            // If characters at current positions match,
            // continue
            if (s.charAt(i) == s.charAt(j)) {
                continue;
            }
            // If one character is '?' and the other isn't,
            // replace the '?' with the other character
            else if (s.charAt(i) == '?'
                     && s.charAt(j) != '?') {
                s = s.substring(0, i) + s.charAt(j)
                    + s.substring(i + 1);
            }
            else if (s.charAt(i) != '?'
                     && s.charAt(j) == '?') {
                s = s.substring(0, j) + s.charAt(i)
                    + s.substring(j + 1);
            }
            // If neither character is '?', it's not
            // possible to make the string palindromic, so
            // return -1
            else {
                return -1;
            }
        }
 
        // Calculate the number of characters to consider
        n = len_s / 2;
        if (len_s % 2 == 1) {
            n++;
        }
 
        // Find the first non-'?' character in the first
        // half of the string
        for (i = 0; i < n; i++) {
            if (s.charAt(i) != '?') {
                last = s.charAt(i);
                break;
            }
        }
 
        // Iterate over the remaining characters and
        // calculate the minimum sum of absolute differences
        // between adjacent characters
        for (i = i + 1; i < n; i++) {
            if (s.charAt(i) == '?') {
                continue;
            }
            diff = Math.abs(s.charAt(i) - last);
            ans += diff;
            last = s.charAt(i);
        }
 
        // Multiply the minimum sum by 2 and return it
        return 2 * ans;
    }
 
    public static void main(String[] args)
    {
        String s = "a???c??c????";
        System.out.println(minimumSum(s));
    }
}




def minimumSum(s):
    # Initialize variables
    i, j, n, len_s, diff, ans = 0, 0, 0, len(s), 0, 0
    last = ''
 
    # Iterate over the string s from both ends simultaneously
    for i, j in zip(range(len_s//2), range(len_s-1, len_s//2-1, -1)):
        # If characters at current positions match, continue
        if s[i] == s[j]:
            continue
        # If one character is '?' and the other isn't, replace the '?' with the other character
        elif s[i] == '?' and s[j] != '?':
            s = s[:i] + s[j] + s[i + 1:]
        elif s[i] != '?' and s[j] == '?':
            s = s[:j] + s[i] + s[j + 1:]
        # If neither character is '?', it's not possible to make the string palindromic, so return -1
        else:
            return -1
 
    # Calculate the number of characters to consider
    n = len_s // 2 if len_s % 2 == 0 else len_s // 2 + 1
 
    # Find the first non-'?' character in the first half of the string
    for i in range(n):
        if s[i] != '?':
            last = s[i]
            break
 
    # Iterate over the remaining characters and calculate the minimum sum of absolute differences between adjacent characters
    for i in range(i + 1, n):
        if s[i] == '?':
            continue
        diff = abs(ord(s[i]) - ord(last))
        ans += diff
        last = s[i]
 
    # Multiply the minimum sum by 2 and return it
    return 2 * ans
 
 
if __name__ == "__main__":
    s = "a???c??c????"
    result = minimumSum(s)
    print(result)




// C++ code for the above approach:
using System;
 
public class Program
{
    public static int MinimumSum(string s)
    {
        int n, len_s, diff, ans = 0;
        char last = '\0';
 
        len_s = s.Length;
 
        // Iterate over the string s from both ends simultaneously
        for (int i = 0, j = len_s - 1; i < j; i++, j--)
        {
            // If characters at current positions match, continue
            if (s[i] == s[j])
            {
                continue;
            }
 
            // If one character is '?' and the other isn't, replace the '?' with the other character
            else if (s[i] == '?' && s[j] != '?')
            {
                s = s.Substring(0, i) + s[j] + s.Substring(i + 1);
            }
            else if (s[i] != '?' && s[j] == '?')
            {
                s = s.Substring(0, j) + s[i] + s.Substring(j + 1);
            }
 
            // If neither character is '?', it's not possible to make the string palindromic, so return -1
            else
            {
                return -1;
            }
        }
 
        // Calculate the number of characters to consider
        n = len_s / 2;
        if (len_s % 2 == 1)
        {
            n++;
        }
 
        // Find the first non-'?' character in the first half of the string
        for (int i = 0; i < n; i++)
        {
            if (s[i] != '?')
            {
                last = s[i];
                break;
            }
        }
 
        // Iterate over the remaining characters and calculate the minimum sum of absolute differences between adjacent characters
        for (int i = n; i < len_s; i++)
        {
            if (s[i] == '?')
            {
                continue;
            }
            diff = Math.Abs(s[i] - last);
            ans += diff;
            last = s[i];
        }
 
        // Multiply the minimum sum by 2 and return it
        return ans;
    }
 
    public static void Main(string[] args)
    {
        string s = "a???c??c????";
 
        // Function call
        Console.WriteLine(MinimumSum(s));
    }
}
// This code was contributed by codearcade




// JavaScript code for the above approach:
function minimumSum(s) {
     
    // Initialize variables
    let i = 0, j = 0, n = 0, len_s = s.length, diff = 0, ans = 0;
    let last = '';
 
    // Iterate over the string s from both
    // ends simultaneously
    for (i = 0, j = len_s - 1; i < j; i++, j--) {
         
        // If characters at current
        // positions match, continue
        if (s[i] == s[j]) {
            continue;
        }
        // If one character is '?' and the
        // other isn't, replace the '?'
        // with the other character
        else if (s[i] == '?' && s[j] != '?') {
            s = s.substring(0, i) + s[j] + s.substring(i + 1);
        }
        else if (s[i] != '?' && s[j] == '?') {
            s = s.substring(0, j) + s[i] + s.substring(j + 1);
        }
        // If neither character is '?',
        // it's not possible to make the
        // string palindromic, so return -1
        else {
            return -1;
        }
    }
 
    // Calculate the number of
    // characters to consider
    n = len_s % 2 == 0 ? len_s / 2 : Math.floor(len_s / 2) + 1;
 
    // Find the first non-'?' character in
    // the first half of the string
    for (i = 0; i < n; i++) {
        if (s[i] != '?') {
            last = s[i];
            break;
        }
    }
 
    // Iterate over the remaining characters
    // and calculate the minimum sum of
    // absolute differences between
    // adjacent characters
    for (i = i + 1; i < n; i++) {
        if (s[i] == '?') {
            continue;
        }
        diff = Math.abs(s[i].charCodeAt(0) - last.charCodeAt(0));
        ans += diff;
        last = s[i];
    }
 
    // Multiply the minimum sum by
    // 2 and return it
    return 2 * ans;
}
 
// Driver code
let s = "a???c??c????";
console.log(minimumSum(s));
 
// This code is contributed by prasad264

Output
4

Time Complexity: O(N), N is the length of the input string S
Auxiliary Space: O(1)


Article Tags :