前两天面试的时候,面试官出了一题很基础的算法题:给一串字符串,如何消除其中的回文。乍一看是很基础的算法题,不过我当时使用的暴力破解法的时间复杂度达到了O(n3),可以说是很烂的一个算法了(这里不再贴出代码,没什么意义)。之后到网上寻求了各种帮助,总结了两个基于栈的实现方法:
一:返回无回文字段(包括清除后有可能存在的回文字段)
public class PlalindromeArithmetic {
public static String clearPlalindrome(String inputStr){
//当长度大于2时才可能存在回文
if (inputStr.length() < 2){
return inputStr;
}
char[] inputChars = inputStr.toCharArray();
char[] outputChars = new char[1000];
char[] termChars = new char[1000];
int j = 0;
for (char inputChar:inputChars){
//此处若栈内无元素则直接入栈
if (termChars[j] == '\u0000'){
termChars[j] = inputChar;
}else {
//此处栈内有元素,判断栈顶元素outputChars[j]是否等于入栈元素inputChar,相等则弹出栈顶元素
//此处判断123321类回文
if (termChars[j] == inputChar){
termChars[j] = '\u0000';
if (j != 0){
j -= 1;
}
//在栈顶元素不等于入栈元素的情况下,判断栈元素是否大于2,若大于2则判断栈顶的下一个元素outputChars[j-1]是否等于入栈元素inputChar
//此处判断12321类回文
} else if (j-1 >= 0 && termChars[j-1] == inputChar){
termChars[j] = '\u0000';
j -= 1;
termChars[j] = '\u0000';
if (j != 0){
j -= 1;
}
//在栈顶元素以及栈顶下一元素都不等于入栈元素的情况下,入栈
} else {
j += 1;
termChars[j] = inputChar;
}
}
}
return String.copyValueOf(outputChars);
}
}
注意:该方法返回的字符串是完全无回文的字符串,例如"1232212342"输出"2342":"1232212342"->"1212342"->"2342"
二、标记-清除-保护(仅删除输入串中所有的回文元素,新生成的回文字符串不进行判断)
public static String clearPlalindromeWithStackV2(String inputStr) {
//当长度大于2时才可能存在回文
if (inputStr.length() < 2) {
return inputStr;
}
char[] inputChars = inputStr.toCharArray();
char[] outputChars = new char[1000];
int j = 0;
int i = j;
int protect = 0;
for (char inputChar : inputChars) {
//此处若栈内无元素则直接入栈
if (outputChars[j] == '\u0000') {
outputChars[j] = inputChar;
i = j;
} else {
//此处栈内有元素,判断栈顶元素outputChars[i]是否等于入栈元素inputChar,相等则标记栈顶元素并向下遍历
//此处判断123321类回文
if (outputChars[i] == inputChar) {
if (i == 0){
while(j >= 0){
outputChars[j] = '\u0000';
j--;
if (j<0){
j++;
break;
}
}
protect = 0;
}else {
j++;
outputChars[j] = inputChar;
i--;
}
//在栈顶元素不等于入栈元素的情况下,判断栈第i-1个元素是否大于被保护元素下标protect,若大于protect则判断下一个元素outputChars[i-1]是否等于入栈元素inputChar
//此处判断12321类回文
}else if (i-1 > protect && outputChars[i-1] == inputChar){
if (j-i == 0){
i--;
}
j++;
outputChars[j] = inputChar;
i--;
}else {
//每次清除的时候将栈顶元素设置为被保护元素,该元素不再有可能被新生成的回文所识别判断
if (i != j){
while(j > i){
outputChars[j] = '\u0000';
if (j > 0){
j--;
};
}
protect = i;
}
j++;
outputChars[j] = inputChar;
i = j;
}
}
}
return String.copyValueOf(outputChars);
}
此方法是我根据方案一进行的修改,在方案一中,每次弹出栈新生成的栈顶元素的下一元素都有可能被对比,而这个方案则将该元素进行保护,新生成的字符串仍然有可能输出新的回文字段,例如"721237221456554"输出"7371454"。
本代码仅提供思路,稍加修改也可用于寻找所有字符串,寻找最长字符串等算法,这边就不再贴出详细代码,核心思想都是一样的。
本人初学算法,代码和思路的实现还有很多瑕疵,欢迎各位大神提供更优方案。