Open In App

Palindrome by swapping only one character

Last Updated : 17 Aug, 2022
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string, the task is to check if the string can be made palindrome by swapping a character only once. 

[NOTE: only one swap and only one character should be swapped with another character]

Examples:  

Input : bbg
Output : true
Explanation: Swap b(1st index) with g.

Input : bdababd
Output : true
Explanation: Swap b(0th index) with d(last index) or
             Swap d(1st index) with b(second index)

Input : gcagac
Output : false

Approach:  

This algorithm was based on a thorough analysis of the behavior and possibility of the forming string palindrome. By this analysis, I got the following conclusions :

  1. Firstly, we will be finding the differences in the string that actually prevents it from being a palindrome. 
    1. To do this, We will start from both the ends and comparing one element from each end at a time, whenever it does match we store the values in a separate array as along with this we keep a count on the number of unmatched items.   
  2. If the number of unmatched items is more than 2, it is never possible to make it a palindrome string by swapping only one character.   
  3. If (number of unmatched items = 2) - it is possible to make the string palindrome if the characters present in first unmatched set are same as the characters present in second unmatched set. (For example : try this out "bdababd").
  4.  If (number of unmatched items = 1) 
    1. if (length of string is even) - it is not possible to make a palindrome string out of this. 
    2. if (length of string is odd) - it is possible to make a palindrome string out of this if one of the unmatched character matches with the middle character.
  5. If (number of unmatched items = 0) - palindrome is possible if we swap the position of any same characters.

Implementation:

C++
// C++ program palindrome by swapping
// only one character
#include <bits/stdc++.h>
using namespace std;

bool isPalindromePossible(string input)
{
    int len = input.length();

    // counts the number of differences 
    // which prevents the string from
    // being palindrome.
    int diffCount = 0, i;

    // keeps a record of the characters 
    // that prevents the string from 
    // being palindrome.
    char diff[2][2];

    // loops from the start of a string 
    // till the midpoint of the string
    for (i = 0; i < len / 2; i++)
    {

        // difference is encountered preventing 
        // the string from being palindrome
        if (input[i] != input[len - i - 1]) 
        {
            
            // 3rd differences encountered and 
            // its no longer possible to make 
            // is palindrome by one swap
            if (diffCount == 2) return false;

            // record the different character
            diff[diffCount][0] = input[i];

            // store the different characters
            diff[diffCount++][1] = input[len - i - 1];
        }
    }
    
    switch (diffCount)
    {
        // its already palindrome
        case 0:
            return true;

        // only one difference is found
        case 1: 
        {
            char midChar = input[i];

            // if the middleChar matches either of
            // the difference producing characters,
            // return true
            if (len % 2 != 0 and
               (diff[0][0] == midChar or
                diff[0][1] == midChar))
                return true;
        }
        
        // two differences are found
        case 2:

            // if the characters contained in 
            // the two sets are same, return true
            if ((diff[0][0] == diff[1][0] and 
                 diff[0][1] == diff[1][1]) or
                (diff[0][0] == diff[1][1] and 
                 diff[0][1] == diff[1][0]))
                return true;
    }
    return false;
}

// Driver Code
int main() 
{
    cout << boolalpha 
         << isPalindromePossible("bbg") << endl;
    cout << boolalpha
         << isPalindromePossible("bdababd") << endl;
    cout << boolalpha 
         << isPalindromePossible("gcagac") << endl;

    return 0;
}

// This code is contributed by
// sanjeev2552
Java
// Java program palindrome by swapping
// only one character
class GFG
 {

    public static boolean isPalindromePossible(String input)
    {

        // convert the string to character array
        char[] charStr = input.toCharArray();
        int len = input.length(), i;

        // counts the number of differences which prevents
        // the string from being palindrome.
        int diffCount = 0;

        // keeps a record of the characters that prevents
        // the string from being palindrome.
        char[][] diff = new char[2][2];

        // loops from the start of a string till the midpoint
        // of the string
        for (i = 0; i < len / 2; i++) {

            // difference is encountered preventing the string
            // from being palindrome
            if (charStr[i] != charStr[len - i - 1]) {

                // 3rd differences encountered and its no longer
                // possible to make is palindrome by one swap
                if (diffCount == 2)
                    return false;

                // record the different character
                diff[diffCount][0] = charStr[i];

                // store the different characters
                diff[diffCount++][1] = charStr[len - i - 1];
            }
        }

        switch (diffCount) {

        // its already palindrome
        case 0:
            return true;

        // only one difference is found
        case 1:
            char midChar = charStr[i];

            // if the middleChar matches either of the
            // difference producing characters, return true
            if (len % 2 != 0 && (diff[0][0] == midChar
                                 || diff[0][1] == midChar))
                return true;

        // two differences are found
        case 2:

            // if the characters contained in the two sets are same,
            // return true
            if ((diff[0][0] == diff[1][0] && diff[0][1] == diff[1][1])
                || (diff[0][0] == diff[1][1] && diff[0][1] == diff[1][0]))
                return true;
        }
        return false;
    }

    public static void main(String[] args)
    {
        System.out.println(isPalindromePossible("bbg"));
        System.out.println(isPalindromePossible("bdababd"));
        System.out.println(isPalindromePossible("gcagac"));
    }
}
Python3
# Python3 program palindrome by swapping
# only one character

def isPalindromePossible(input: str) -> bool:
    length = len(input)

    # counts the number of differences
    # which prevents the string from
    # being palindrome.
    diffCount = 0
    i = 0

    # keeps a record of the characters
    # that prevents the string from
    # being palindrome.
    diff = [['0'] * 2] * 2

    # loops from the start of a string
    # till the midpoint of the string
    while i < length // 2:

        # difference is encountered preventing
        # the string from being palindrome
        if input[i] != input[length - i - 1]:

            # 3rd differences encountered and
            # its no longer possible to make
            # is palindrome by one swap
            if diffCount == 2:
                return False

            # record the different character
            diff[diffCount][0] = input[i]

            # store the different characters
            diff[diffCount][1] = input[length - i - 1]
            diffCount += 1
        i += 1

    # its already palindrome
    if diffCount == 0:
        return True

    # only one difference is found
    elif diffCount == 1:
        midChar = input[i]

        # if the middleChar matches either of
        # the difference producing characters,
        # return true
        if length % 2 != 0 and (diff[0][0] == midChar
                                or diff[0][1] == midChar):
            return True

    # two differences are found
    elif diffCount == 2:

        # if the characters contained in
        # the two sets are same, return true
        if (diff[0][0] == diff[1][0] and diff[0][1] == diff[1][1]) or (
                diff[0][0] == diff[1][1] and diff[0][1] == diff[1][0]):
            return True
    return False

# Driver Code
if __name__ == "__main__":

    print(isPalindromePossible("bbg"))
    print(isPalindromePossible("bdababd"))
    print(isPalindromePossible("gcagac"))

# This code is contributed by
# sanjeev2552
C#
// C# program palindrome by swapping
// only one character
using System;

class GFG 
{ 

    public static bool isPalindromePossible(String input) 
    { 

        // convert the string to character array 
        char[] charStr = input.ToCharArray(); 
        int len = input.Length, i; 

        // counts the number of differences 
        // which prevents the string
        // from being palindrome. 
        int diffCount = 0; 

        // keeps a record of the 
        // characters that prevents 
        // the string from being palindrome. 
        char[,] diff = new char[2, 2]; 

        // loops from the start of a string 
        // till the midpoint of the string 
        for (i = 0; i < len / 2; i++)
        { 

            // difference is encountered preventing 
            // the string from being palindrome 
            if (charStr[i] != charStr[len - i - 1]) 
            { 

                // 3rd differences encountered 
                // and its no longer possible to
                // make is palindrome by one swap 
                if (diffCount == 2) 
                    return false; 

                // record the different character 
                diff[diffCount, 0] = charStr[i]; 

                // store the different characters 
                diff[diffCount++, 1] = charStr[len - i - 1]; 
            } 
        } 

        switch (diffCount) 
        { 

            // its already palindrome 
            case 0: 
                return true; 

            // only one difference is found 
            case 1: 
                char midChar = charStr[i]; 

            // if the middleChar matches either of the 
            // difference producing characters, return true 
            if (len % 2 != 0 && 
                (diff[0,0] == midChar || 
                diff[0,1] == midChar)) 
                return true; 
            break;
        
            // two differences are found 
            case 2: 

            // if the characters contained in 
            // the two sets are same, return true 
            if ((diff[0,0] == diff[1,0] && 
                 diff[0,1] == diff[1,1]) ||
                 (diff[0,0] == diff[1,1] && 
                 diff[0,1] == diff[1,0])) 
                return true; 
            break;
        } 
        return false; 
    } 

    // Driver code
    public static void Main(String[] args) 
    { 
        Console.WriteLine(isPalindromePossible("bbg")); 
        Console.WriteLine(isPalindromePossible("bdababd")); 
        Console.WriteLine(isPalindromePossible("gcagac")); 
    } 
} 

// This code is contributed by PrinciRaj1992
JavaScript
<script>

// JavaScript program palindrome by swapping
// only one character

function isPalindromePossible(input){
    
    let Length = input.length

    // counts the number of differences
    // which prevents the string from
    // being palindrome.
    let diffCount = 0,i = 0

    // keeps a rec||d of the characters
    // that prevents the string from
    // being palindrome.
    let diff = new Array(2).fill(0).map(()=>new Array(2))

    // loops from the start of a string
    // till the midpoint of the string
    for (i = 0; i < Math.floor(Length / 2); i++)
    {

        // difference is encountered preventing
        // the string from being palindrome
        if(input[i] != input[Length - i - 1]){

            // 3rd differences encountered &&
            // its no longer possible to make
            // is palindrome by one swap
            if(diffCount == 2)
                return false

            // rec||d the different character
            diff[diffCount][0] = input[i]

            // st||e the different characters
            diff[diffCount++][1] = input[Length - i - 1]
        }
    }

    switch (diffCount)
    {
        // its already palindrome
        case 0:
            return true
 
        // only one difference is found
        case 1:
        {
            let midChar = input[i]
 
            // if the middleChar matches either of
            // the difference producing characters,
            // return true
            if (Length % 2 != 0 &&
               (diff[0][0] == midChar ||
                diff[0][1] == midChar))
                return true
        }
         
        // two differences are found
        case 2:
 
            // if the characters contained in
            // the two sets are same, return true
            if ((diff[0][0] == diff[1][0] &&
                 diff[0][1] == diff[1][1]) ||
                (diff[0][0] == diff[1][1] &&
                 diff[0][1] == diff[1][0]))
                return true
    }
    return false
}

// driver code

document.write(isPalindromePossible("bbg"),"</br>")
document.write(isPalindromePossible("bdababd"),"</br>")
document.write(isPalindromePossible("gcagac"),"</br>")

// This code is contributed by shinjanpatra

</script>

Output
true
true
false

Complexity Analysis:

  • Time Complexity : O(n) 
  • Auxiliary Space : O(1) 

Article Tags :
Practice Tags :

Similar Reads