Problem
Given a string s containing lowercase English letters and the character ?.
We have to replace every ? with a lowercase English letter so that the final string becomes a palindrome.
Among all possible palindromes, we need to find the one having the minimum sum of absolute ASCII differences between adjacent characters.
If it is impossible to make the string a palindrome, return -1.
Example
Input:
s = "a???c??c????"
Output:
4One possible palindrome is:
abbbccccbbbaThe adjacent differences are:
|a-b| = 1
|b-b| = 0
|b-b| = 0
|b-c| = 1
|c-c| = 0
|c-c| = 0
|c-c| = 0
|c-b| = 1
|b-b| = 0
|b-b| = 0
|b-a| = 1Total:
1 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 1 = 4Understanding the Palindrome Property
A palindrome reads the same from left to right and right to left.
For example:
abcbaThe matching positions are:
a ↔ a
b ↔ b
c ↔ c
b ↔ b
a ↔ aFor a string of length n, position i must be equal to:
n - 1 - iTherefore, for every pair:
s[i] and s[n - 1 - i]we have three possibilities.
Case 1: Both are fixed characters
Example:
a ... aThis is valid because both characters are already equal.
But:
a ... cis impossible because neither character can be changed.
So we return:
-1Case 2: One character is ?
Example:
a ... ?The ? must become:
aSimilarly:
? ... cmust become:
cSo there is only one possible choice.
Case 3: Both characters are ?
Example:
? ... ?Both characters must become the same character.
We have complete freedom to choose that character.
To minimize the adjacent difference, we can choose a character that continues the previous fixed character.
For example:
a ? ? ccan become:
a a a cinstead of unnecessarily introducing another character.
Therefore, the ? region does not create an additional cost between fixed characters.
Important Observation
Instead of constructing the entire palindrome, we can process only the left half of the string.
Why?
Consider:
a b c c b aThe adjacent differences are:
a-b
b-c
c-c
c-b
b-aThe right half contains the same differences in reverse order.
Therefore:
Total cost = 2 × cost of the left halfSo we only need to find the minimum cost between consecutive characters in the left half.
Another Important Observation
Suppose the fixed characters that appear while scanning the left half are:
a → c → fThe minimum cost is:
|a-c| + |c-f|The ? characters between them can simply be replaced with the previous character.
For example:
a ? ? c ? ? fcan become:
a a a c c c fThe cost becomes:
|a-a| + |a-a| + |a-c| + |c-c| + |c-c| + |c-f|Only the transitions between fixed characters contribute:
|a-c| + |c-f|Since the same transitions appear on the other side of the palindrome, multiply by 2.
Algorithm
We maintain a variable called previous.
It represents the previous fixed character that we encountered in the left half.
For every mirrored pair:
left = s[i]
right = s[n - 1 - i]we do the following:
Step 1: Check if both are fixed
If:
left != '?' && right != '?'then they must be equal.
If:
left != rightreturn:
-1Otherwise, this pair represents that character.
Step 2: If only one is fixed
If one side is ?, the other character determines what it must become.
For example:
a ?becomes:
a aSo we use a.
Step 3: If both are ?
There is no fixed character that needs to be added.
We can continue without adding a cost.
Step 4: Calculate the difference
When we find a new fixed character:
currentand already have:
previousthe cost between them is:
Math.abs(current - previous)Because the same transition appears on the other half:
answer += 2 * Math.abs(current - previous);Java Implementation
class Solution {
public int minimumSum(String s) {
int n = s.length();
int answer = 0;
char previous = 0;
boolean hasPrevious = false;
// Process only the left half
for (int i = 0; i < n / 2; i++) {
char left = s.charAt(i);
char right = s.charAt(n - 1 - i);
char current;
// Both characters are fixed
if (left != '?' && right != '?') {
// Different characters cannot be changed
if (left != right) {
return -1;
}
current = left;
}
// Left character is fixed
else if (left != '?') {
current = left;
}
// Right character is fixed
else if (right != '?') {
current = right;
}
// Both characters are '?'
else {
continue;
}
// Calculate difference from previous fixed character
if (hasPrevious) {
answer += 2 * Math.abs(current - previous);
}
previous = current;
hasPrevious = true;
}
return answer;
}
}Code ExplanationLet's understand the important parts of the code.
1. Store the length
int n = s.length();We need the length to find the mirrored character.
For index i, its corresponding character is:
n - 1 - i2. Store the answer
int answer = 0;This stores the minimum total adjacent difference.
3. Store the previous fixed character
char previous = 0;
boolean hasPrevious = false;previous stores the previous character that is fixed or determined.
For example:
a ? ? c ? fwhile scanning, we get:
a → c → fSo:
previous = a
previous = c
previous = f4. Process only half the string
for (int i = 0; i < n / 2; i++)We don't need to process the complete string because the right half is the mirror image.
This also makes the solution efficient.
5. Find the mirrored characters
char left = s.charAt(i);
char right = s.charAt(n - 1 - i);For example:
s = "abcba"When:
i = 0we get:
left = 'a'
right = 'a'When:
i = 1we get:
left = 'b'
right = 'b'Handling Fixed Characters
if (left != '?' && right != '?') {Both characters are known.
For example:
a ... ais valid.
But:
a ... cis impossible.
Therefore:
if (left != right) {
return -1;
}Handling One
?else if (left != '?') {
current = left;
}If the left character is fixed, the right ? must become the same character.
For example:
a ... ?becomes:
a ... aSimilarly:
else if (right != '?') {
current = right;
}handles:
? ... cwhich becomes:
c ... cHandling Two
?else {
continue;
}When both characters are ?, we don't have a fixed character to process.
We can choose a suitable character later without increasing the minimum cost.
Calculating the Cost
This is the most important line:
answer += 2 * Math.abs(current - previous);Suppose:
previous = 'a'
current = 'c'ASCII values are:
'a' = 97
'c' = 99Therefore:
|97 - 99| = 2The same transition appears on the other side of the palindrome.
So:
2 × 2 = 4is added to the answer.
Dry Run
Consider:
s = "a???c??c????"We process the mirrored pairs.
The important fixed characters encountered from the left half are:
a
cThe transition is:
a → cASCII difference:
|97 - 99| = 2Because it appears on both sides:
2 × 2 = 4Therefore:
answer = 4Why This Greedy Approach Works
The important point is that a sequence of ? characters between two fixed characters does not force us to create additional cost.
Suppose:
a ? ? ? cWe can choose:
a a a a cThe cost is:
|a-a| + |a-a| + |a-a| + |a-c|which is simply:
0 + 0 + 0 + |a-c|So there is no benefit in choosing intermediate characters such as:
a b c d cbecause that would create unnecessary differences.
Thus, we only need to consider the transitions between consecutive fixed characters.
Complexity Analysis
Let n be the length of the string.
Time Complexity
O(n)We scan approximately half of the string.
Since:
n / 2 = O(n)the overall complexity is O(n).
Auxiliary Space
O(1)We only use a few variables:
answer
previous
hasPrevious
left
right
currentNo additional array or string is required.
Key Takeaways
The main ideas used in this problem are:
Palindrome property
s[i] == s[n-1-i]Check mirrored characters
Same fixed characters → valid.
Different fixed characters → impossible.
?+ fixed → replace?with the fixed character.?+?→ choose a suitable character.
Process only half of the string.
Ignore consecutive
?regions when calculating cost, because they can be filled with the previous character.Every transition occurs twice in a palindrome, so:
total cost = 2 × left-half costThe final solution runs in:
Time: O(n) Space: O(1)
Pattern to Remember
When you see a problem involving:
Palindrome + '?' + minimum costfirst think about the mirrored pairs:
i ↔ n - 1 - iThen think about the fixed characters and the cost between consecutive fixed characters. This reduces the problem from constructing many possible strings to a simple linear scan.

Join the conversation! Your thoughts help the community grow.