05.leetCode之求最长子串(秃头写不出来版)

文章介绍了使用暴力枚举和中心扩散法来找出字符串中最长的回文子串。暴力枚举方法通过遍历所有可能的子串并检查是否为回文,存在较高的时间复杂度。中心扩散法以字符串中的每个字符为中心,向两侧扩散,有效减少了计算量。文章强调了算法优化的重要性,包括函数式思维、分步实现和边界条件处理。
摘要由CSDN通过智能技术生成

1.暴力枚举(--其实我还不会写,有待改进的地方是先把枚举学懂是学习算法的第一步…)O(n^3)通不过测试--

要改进的地方:
1.要有函数式的思维(把过程拆分为多个函数)
2.提前写好算法步骤再逐步优化
3.要有从1个数据到多个数据分类讨论的思想(画思维导图)
4.刚开始学不要贪图时间复杂度大小,能写出来再优化
5.把大困难分解成为多个小困难
代码思路:
1.字符串长度为1时直接返回
2.枚举全部情况的字符组合顺序(先去思考怎么把元素全部列举出来)
3.需要的步骤包括 列举每个值的函数和判断单个字符是回文数的函数
4.枚举字符串的套路可以记下来,因为是固定的,由于subString的特点(第二个值是去闭区间的),所以循环的j变量要<=s.length();
5.如果当前最大回文数的长度大于之前遍历的长度,则更新长度
6.判断是否是回文数的函数就是一一在中间对称对比字符串,前面的从0开始,后面的从length-i-1开始,i的条件是;length/2.在中间结束循环
7. 6的判断为什么不考虑回文数的奇数偶性呢? 因为length/2刚刚好处理了对称问题…
---- 如 abc length/2=1 中心在b刚刚好不用对比, abba 中心在length/2=2中心在b
----当i加到2的时候刚刚好,落在index=2的b,
----s.charAt(2)!=s.charAt(2) b=b所以不用处理了

//暴力解法
class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        String abc = solution.longestPalindrome("aacabdkacaa");
        System.out.println(abc);

    }
    public String longestPalindrome(String s) {
        //长度为1的字符串的单独考虑
        if(s.length()==1)  return s;
        int maxlength=0;
        String ans="";
        for(int i=0;i<s.length()-1;i++){
            //注意j<=s.length(),因为substring(i,j) 截取的字符串区间是前闭后开的,即[i,j)
            for(int j=i+1;j<=s.length();j++){
                String temp=s.substring(i,j);
                if(isPalindrome(temp)&&temp.length()>maxlength){
                    ans=temp;
                    maxlength=ans.length();
                }
            }
        }
        return ans;
    }
    //判断是否是回文串的函数
    public boolean isPalindrome(String s){
        int length=s.length();
        for(int i=0;i<length/2;i++){
            if(s.charAt(i)!=s.charAt(length-i-1)){
                return false;
            }
        }
        return true;
    }
}

2.中心扩散法(大佬的方法)

个人总结:
0.中心扩散法是指从中心一个特定的值,扩散到他两边的值
1.中间的值对比两边的值,设了三个变量 left(左边的下标) right(右边的下标) len(找到的长度)
2.中间的值对比两边的值, 左边找到了 就 left–.右边找到了就right++
3.如果都没有找到,那么直接对比 ,left-1和right+1的值 如果相等就len+2 ,否则 介绍寻找

实践调试代码后的总结
1.为什么叫中心扩散法,就是以for循环的i下标为中心!!! 然后i的下标的值对比两边的值
2.如果相等向外面扩散,最后一步是如果扩散后的值相等则长度+2.继续扩散
3.注意len都会清零,还是会重复对比中心继续扩散,直到i到length
4.但是注意边界条件, 也是套路 0 和length是常见的边界条件,left>=0和right<=length也是常见的套路

思路请添加图片描述

代码:

public class test02 {
    public static void main(String[] args) {
        test02 test02 = new test02();
        String res = test02.longestPalindrome1("aabb");
        System.out.println(res);
    }

    public String longestPalindrome1(String s) {
        //判空,??为什么是长度为1的时候不直接返回??
        if (s == null || s.length() == 0) {
            return "";
        }
        //得到字符串长度
        int strLen = s.length();
        //左边字符的下标
        int left = 0;
        //右边边字符的下标
        int right = 0;
        //???长度为什么为1??? 答:  因为必须肯定要最少一个数进行对比
        int len = 1;
        //最大子串的开始下标
        int maxStart = 0;
        //最大的长度
        int maxLen = 0;

        for (int i = 0; i < strLen; i++) {
            left = i - 1;
            right = i + 1;
            while (left >= 0 && s.charAt(left) == s.charAt(i)) {
                len++;
                left--;
            }
            while (right < strLen && s.charAt(right) == s.charAt(i)) {
                len++;
                right++;
            }
            while (left >= 0 && right < strLen && s.charAt(right) == s.charAt(left)) {
                len = len + 2;
                left--;
                right++;
            }
            if (len > maxLen) {
                maxLen = len;
                maxStart = left;
            }
            //黑人问号??? 为什么len重置为1? 答:接下来的循环会继续寻找 其他子串
            len = 1;
        }
        return s.substring(maxStart + 1, maxStart + maxLen + 1);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值