算法学习之路:去除字符串中的回文字段

       前两天面试的时候,面试官出了一题很基础的算法题:给一串字符串,如何消除其中的回文。乍一看是很基础的算法题,不过我当时使用的暴力破解法的时间复杂度达到了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"。

 

本代码仅提供思路,稍加修改也可用于寻找所有字符串,寻找最长字符串等算法,这边就不再贴出详细代码,核心思想都是一样的。

 

本人初学算法,代码和思路的实现还有很多瑕疵,欢迎各位大神提供更优方案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值