Hard
You are given a string s consisting of lowercase English letters.
You can perform the following operation any number of times (including zero):
'a' and 'b', or 'b' and 'a').Return the lexicographically smallest string that can be obtained after performing the operations optimally.
Note: Consider the alphabet as circular, thus 'a' and 'z' are consecutive.
Example 1:
Input: s = “abc”
Output: “a”
Explanation:
"bc" from the string, leaving "a" as the remaining string."a".Example 2:
Input: s = “bcda”
Output: “”
Explanation:
"cd" from the string, leaving "ba" as the remaining string."ba" from the string, leaving "" as the remaining string."".Example 3:
Input: s = “zdce”
Output: “zdce”
Explanation:
"dc" from the string, leaving "ze" as the remaining string."ze"."zdce" is lexicographically smaller than "ze", the smallest string after all possible removals is "zdce".Constraints:
1 <= s.length <= 250s consists only of lowercase English letters.public class Solution {
private boolean checkPair(char char1, char char2) {
int diffVal = Math.abs(char1 - char2);
return diffVal == 1 || (char1 == 'a' && char2 == 'z') || (char1 == 'z' && char2 == 'a');
}
public String lexicographicallySmallestString(String sIn) {
int nVal = sIn.length();
if (nVal == 0) {
return "";
}
boolean[][] remTable = new boolean[nVal][nVal];
for (int len = 2; len <= nVal; len += 2) {
for (int idx = 0; idx <= nVal - len; idx++) {
int j = idx + len - 1;
if (checkPair(sIn.charAt(idx), sIn.charAt(j))) {
if (len == 2) {
remTable[idx][j] = true;
} else {
if (remTable[idx + 1][j - 1]) {
remTable[idx][j] = true;
}
}
}
if (remTable[idx][j]) {
continue;
}
for (int pSplit = idx + 1; pSplit < j; pSplit += 2) {
if (remTable[idx][pSplit] && remTable[pSplit + 1][j]) {
remTable[idx][j] = true;
break;
}
}
}
}
String[] dpArr = new String[nVal + 1];
dpArr[nVal] = "";
for (int idx = nVal - 1; idx >= 0; idx--) {
dpArr[idx] = sIn.charAt(idx) + dpArr[idx + 1];
for (int kMatch = idx + 1; kMatch < nVal; kMatch++) {
if (checkPair(sIn.charAt(idx), sIn.charAt(kMatch))) {
boolean middleVanishes;
if (kMatch - 1 < idx + 1) {
middleVanishes = true;
} else {
middleVanishes = remTable[idx + 1][kMatch - 1];
}
if (middleVanishes) {
String candidate = dpArr[kMatch + 1];
if (candidate.compareTo(dpArr[idx]) < 0) {
dpArr[idx] = candidate;
}
}
}
}
}
return dpArr[0];
}
}