• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:最长回文子串-三种解答

java 搞代码 4年前 (2022-01-27) 53次浏览 已收录 0个评论
文章目录[隐藏]

题目形容

给你一个字符串 s,找到 s 中最长的回文子串。

例子

<code class="txt">示例 1:
输出:s = "babad"
输入:"bab"
解释:"aba" 同样是合乎题意的答案。

示例 2:
输出:s = "cbbd"
输入:"bb"

示例 3:
输出:s = "a"
输入:"a"

示例 4:
输出:s = "ac"
输入:"a"

起源:力扣(LeetCode)
链接:https://leetcode-cn.com/probl…,著作权归领扣网络所有。

思路以及解答

暴力破解

暴力破解,即是针对外面每一个子串,都去判断是否为回文串。

判断每一个字符是不是回文串,比方用 cbac 判断,左右两个指针,对称判断,相等则往两头挪动,持续判断,不相等则间接返回 false 。

<code class="java">    public static String longestPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        String result = s.substring(0, 1);
        for (int i=0; i < s.length() - 1; i++) {
            for (int j = i + 1; j < s.length(); j++) {
                if (judge(s, i, j) && j - i + 1 > result.length()) {
                    result = s.substring(i, j+1);
                }
            }
        }
        return result;
    }
    
    // 判断每个子串是不是回文
    public static boolean judge(String source, int start, int end) {
        // 对称轴比照
        while (start <= end) {
            if (source.charAt(start) != source.charAt(end)) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

暴力破解简单度过高,会超时,不举荐应用。

核心拓展法

回文串总是中心对称的,后面使用暴力法的时候,都是截取出子串之后再判断,只有判断到全副对称,能力证实回文,这样其实走了很多弯路,只有最初一个不对称,半途而废。

反过来想,咱们不如在每一个点,都尝试往两边拓展,这样只有不匹配,就能够及时止顺。

值得注意的是,核心拓展法的核心怎么找?3个字符有多少个核心呢?

一共有五个核心,有些核心可能是两个字符的间隙,有些核心可能是字符。那么设计的时候,咱们用 leftright 示意两个指针:

  • left = right:对称中心为字符
  • left + 1 = right: 对称中心为两个字符的间隙

具体实现如下:

<code class="java">class Solution {
    // 开始下标
    public static int start = -1;
    // 最大长度
    public static int maxLen= 0;
    public String longestPalindrome(String s) {
        start = -1;
        maxLen = 0;
        if(s==null||s.length()==0){
            return "";
        }
        for(int i=0;i<s.length();i++){
            // 以以后字符为对称轴
            judge(s,i,i);
            // 以以后字符和下一个字符的间隙为对称轴
            judge(s,i,i+1);
        }
        if(start == -1){
            return "";
        }
        return s.substring(start,start+maxLen);
    }

    public void judge(String s,int left,int right){
        while(left>=0 && right<s.length() && s.charAt(left)==s.charAt(right)){
            left--;
            right++;
        }
        int size =  right-left-1;
        if(size > maxLen){
            maxLen = size;
            start = left+1;
        }
    }
}

动静布局

其实,一个字符串是回文串的话,那么它倒过去读也是一样的,也就是说,它与它反转后的字符串,其实是齐全匹配的,那么要是咱们用一个字符串和它反转字符串一一统计匹配,是不是就能够失去后果呢?

答案是必定的!假如原字符串为 s1,反转后的字符串为 s2,字符串长度为 n,咱们用数组 nums[n][n] 来记录匹配的数量,nums[i][j]示意以 s1[i] 结尾的字符子串,和以 s2[j]结尾的字符子串,两者的匹配字符的最大数值。

  • s1[i] == s2[j]:

    • 如果 i == 0 或者 j == 0: nums[i][j] = 1
    • 否则 nums[i][j] = nums[i - 1][j - 1] + 1;
  • 如果 s1[i] != s2[j],则 nums[i][j]=0

后面说的其实就是状态转移表达式,也就是 nums[i][j] 是怎么求解的?nums[i][j] 是依赖于 nums[i - 1][j - 1] 和 以后字符是否匹配,如果以后字符不匹配,间接赋值为 0,只有在以后字符匹配的状况下,才会须要看后面一位的匹配数值 nums[i - 1][j - 1]

假如以 babad 为例子:

最初两行的计算:

实现的代码如下:

<code class="java">class Solution {
    public static String longestPalindrome(String s) {
        if (s == null || s.length() == 0) {
            return "";
        }
        if (s.length() == 1) {
            return s;
        }
        int len = s.length();
        String s1 = new StringBuffer(s).reverse().toString();
        int[][] nums = new int[len][len];
        int end = 0, max = 0;
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums.length; j++) {
                if (s1.charAt(i) == s.charAt(j)) {
                    if (i == 0 || j == 0) {
                        nums[i][j] = 1;
                    } else {
                        nums[i][j] = nums[i - 1][j - 1] + 1;
                    }
                }
                if (nums[i][j] > max) {
                    if (len - i - 1 + nums[i][j] - 1 == j) {
                        end = j;
                        max = nums[i][j];
                    }
                }
            }
        }
        return s.substring(end - max+1, end+1);
    }
}

作者简介

【作者简介】
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使迟缓,驰而不息。集体写作方向:Java源码解析JDBCMybatisSpringredis分布式剑指OfferLeetCode等,认真写好每一篇文章,不喜爱题目党,不喜爱花里胡哨,大多写系列文章,不能保障我写的都完全正确,然而我保障所写的均通过实际或者查找材料。脱漏或者谬误之处,还望斧正。

剑指Offer全副题解PDF

2020年我写了什么?

开源编程笔记


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:最长回文子串-三种解答

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址