Welcome to Subscribe On Youtube

3088. Make String Anti-palindrome

Description

We call a string s of even length n an anti-palindrome if for each index 0 <= i < n, s[i] != s[n - i - 1].

Given a string s, your task is to make s an anti-palindrome by doing any number of operations (including zero).

In one operation, you can select two characters from s and swap them.

Return the resulting string. If multiple strings meet the conditions, return the lexicographically smallest one. If it can't be made into an anti-palindrome, return "-1".

 

Example 1:

Input: s = "abca"

Output: "aabc"

Explanation:

"aabc" is an anti-palindrome string since s[0] != s[3] and s[1] != s[2]. Also, it is a rearrangement of "abca".

Example 2:

Input: s = "abba"

Output: "aabb"

Explanation:

"aabb" is an anti-palindrome string since s[0] != s[3] and s[1] != s[2]. Also, it is a rearrangement of "abba".

Example 3:

Input: s = "cccd"

Output: "-1"

Explanation:

You can see that no matter how you rearrange the characters of "cccd", either s[0] == s[3] or s[1] == s[2]. So it can not form an anti-palindrome string.

 

Constraints:

  • 2 <= s.length <= 105
  • s.length % 2 == 0
  • s consists only of lowercase English letters.

Solutions

Solution 1: Greedy + Sorting

The problem asks us to transform the string $s$ into the lexicographically smallest non-palindrome string. We might as well sort the string $s$ first.

Next, we only need to compare whether the two middle characters $s[m]$ and $s[m-1]$ are equal. If they are equal, we find the first character $s[i]$ in the second half that is not equal to $s[m]$, use a pointer $j$ to point to $m$, and then swap $s[i]$ and $s[j]$. If we can’t find such a character $s[i]$, it means that the string $s$ cannot be transformed into a non-palindrome string, return "1". Otherwise, perform the swap operation, move $i$ and $j$ to the right, compare whether $s[j]$ and $s[n-j-1]$ are equal, if they are equal, continue to perform the swap operation until $i$ exceeds the length of the string.

The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the string $s$.

  • class Solution {
        public String makeAntiPalindrome(String s) {
            char[] cs = s.toCharArray();
            Arrays.sort(cs);
            int n = cs.length;
            int m = n / 2;
            if (cs[m] == cs[m - 1]) {
                int i = m;
                while (i < n && cs[i] == cs[i - 1]) {
                    ++i;
                }
                for (int j = m; j < n && cs[j] == cs[n - j - 1]; ++i, ++j) {
                    if (i >= n) {
                        return "-1";
                    }
                    char t = cs[i];
                    cs[i] = cs[j];
                    cs[j] = t;
                }
            }
            return new String(cs);
        }
    }
    
  • class Solution {
    public:
        string makeAntiPalindrome(string s) {
            sort(s.begin(), s.end());
            int n = s.length();
            int m = n / 2;
            if (s[m] == s[m - 1]) {
                int i = m;
                while (i < n && s[i] == s[i - 1]) {
                    ++i;
                }
                for (int j = m; j < n && s[j] == s[n - j - 1]; ++i, ++j) {
                    if (i >= n) {
                        return "-1";
                    }
                    swap(s[i], s[j]);
                }
            }
            return s;
        }
    };
    
  • class Solution:
        def makeAntiPalindrome(self, s: str) -> str:
            cs = sorted(s)
            n = len(cs)
            m = n // 2
            if cs[m] == cs[m - 1]:
                i = m
                while i < n and cs[i] == cs[i - 1]:
                    i += 1
                j = m
                while j < n and cs[j] == cs[n - j - 1]:
                    if i >= n:
                        return "-1"
                    cs[i], cs[j] = cs[j], cs[i]
                    i, j = i + 1, j + 1
            return "".join(cs)
    
    
  • func makeAntiPalindrome(s string) string {
    	cs := []byte(s)
    	sort.Slice(cs, func(i, j int) bool { return cs[i] < cs[j] })
    	n := len(cs)
    	m := n / 2
    	if cs[m] == cs[m-1] {
    		i := m
    		for i < n && cs[i] == cs[i-1] {
    			i++
    		}
    		for j := m; j < n && cs[j] == cs[n-j-1]; i, j = i+1, j+1 {
    			if i >= n {
    				return "-1"
    			}
    			cs[i], cs[j] = cs[j], cs[i]
    		}
    	}
    	return string(cs)
    }
    
  • function makeAntiPalindrome(s: string): string {
        const cs: string[] = s.split('').sort();
        const n: number = cs.length;
        const m = n >> 1;
        if (cs[m] === cs[m - 1]) {
            let i = m;
            for (; i < n && cs[i] === cs[i - 1]; i++);
            for (let j = m; j < n && cs[j] === cs[n - j - 1]; ++i, ++j) {
                if (i >= n) {
                    return '-1';
                }
                [cs[j], cs[i]] = [cs[i], cs[j]];
            }
        }
        return cs.join('');
    }
    
    

All Problems

All Solutions