首页 > 其他分享 >『LeetCode』5. 最长回文子串 Longest Palindromic Substring

『LeetCode』5. 最长回文子串 Longest Palindromic Substring

时间:2023-12-23 23:55:25浏览次数:30  
标签:arr end Palindromic int Substring start Longest 字符串 回文

题目描述

给你一个字符串s,找到s中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2

输入**:s = "cbbd"
输出:"bb"

提示

  • 1 <= s.length <= 1000
  • s仅由数字和英文字母组成

题目链接https://leetcode.cn/problems/longest-palindromic-substring/

『1』暴力解法

解题思路

先使用双重循环,依次枚举字符串s中以各字符为起始的子串,再通过 while 循环判断其是否为回文串,若是则记录其长度,以此过程来获得最长回文子串的长度。

实现代码

class Solution {
    // Brute Force
    // n is the length of s
    // Time Complexity: O(n^3)
    // Space Complexity: O(1)
    public String longestPalindrome(String s) {
        if (s == null || s.isEmpty()) return "";

        // 与 char 数组相比,s.charAt(i) 会进行数组下标越界等检查,因此转为 char 数组会更高效
        // 使用 String:176ms
        // 转为 char[]:85ms
        char[] arr = s.toCharArray();
        int start = 0, end = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                // 做了优化,即先将截取字符串的长度与当前结果的长度进行比较,若大于再进行回文串的判断
                if (j - i + 1 > end - start + 1 && isPalindrome(arr, i, j)) {
                    start = i;
                    end = j;
                }
            }
        }
        // 注意 substring() 方法是左闭右开,因此 end 加1
        return s.substring(start, end + 1);
    }

    private boolean isPalindrome(char[] arr, int left, int right) {
        while (left < right) {
            if (arr[left] != arr[right]) return false;
            ++left;
            --right;
        }
        return true;
    }
}

『2』中心扩散法

解题思路

首先根据回文串的定义,如果一个字符串正着读和反着读是一样的,那它就是回文串。
因此,回文可以从其中心展开。回文串在长度为奇数和偶数的时候,回文串中心的形态不同:中心为一个或两个元素。
对于长度为n的字符串,一个元素为中心的情况有n个,两个元素为中心的情况有n-1个,所以要对这两种情况都做遍历,也就是n + (n - 1) = 2n - 1次,时间复杂度为O(n)
又由于每个回文中心最多会向外扩展O(n)次,因此时间复杂度为O(n^2)

实现代码

class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.isEmpty()) return "";

        // 使用 String:6ms
        // 转为 char[]:16ms
        char[] arr = s.toCharArray();
        int start = 0, end = 0;

        for (int i = 0; i < arr.length - 1; i++) {
            int oddLen = expandAroundCenter(arr, i - 1, i + 1);
            int evenLen = expandAroundCenter(arr, i, i + 1);
            int len = Math.max(oddLen, evenLen);
            if (len > end - start) {
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }
        return s.substring(start, end + 1);
    }

    private int expandAroundCenter(char[] arr, int left, int right) {
        while (left >= 0 && right < arr.length && arr[left] == arr[right]) {
            --left;
            ++right;
        }
        // left 和 right 最后多加了一次
        return right - left - 1;
    }
}

『3』动态规划

解题思路

如果字符串是回文串,两边分别增加一个相同字符,其仍然是回文串;两边分别增加一个不同字符,则其不是回文串。
因此一个字符串是不是回文串,取决于两边的字符是否相同、中间的字符串是不是回文串
当两边字符相同且字符串长度小于4时,该字符串一定是回文串。
参考视频:使用【动态规划】求解最长回文子串

实现代码

class Solution {
    // Dynamic Programming
    // n is the length of s
    // Time Complexity: O(n^2)
    // Space Complexity: O(n^2)
    public String longestPalindrome(String s) {
        if (s == null || s.isEmpty()) return "";

        int n = s.length();
        // 字符串 s[i...j] 是否为回文串
        boolean[][] dp = new boolean[n][n];
        for (int i = 0; i < n; i++) dp[i][i] = true;
        for (int j = 1; j < n; j++) {
            for (int i = 0; i < j; i++) {
                if (s.charAt(i) != s.charAt(j)) {
                    dp[i][j] = false;
                } else {
                    dp[i][j] = j - i < 3 || dp[i + 1][j - 1];
                }
            }
        }
        int start = 0, end = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (j - i + 1 > end - start + 1 && dp[i][j]) {
                    start = i;
                    end = j;
                }
            }
        }
        return s.substring(start, end + 1);
    }
}

标签:arr,end,Palindromic,int,Substring,start,Longest,字符串,回文
From: https://www.cnblogs.com/torry2022/p/17923865.html

相关文章

  • 『LeetCode』3. 无重复字符的最长子串 Longest Substring Without Repeating Characte
    『1』双指针算法我的想法:一般看到字符串子串问题想到用双指针解,看到字符串子序列问题想到用动态规划解。此题用双指针可以很快解题。遍历字符串中的每个字符s.charAt[i],对于每一个i,找到j使得双指针[j,i]维护的是以s.charAt[i]结尾的无重复字符的最长子串,长度为i-j+1,......
  • CF Edu160F Palindromic Problem
    赛时过的人少估计是因为难调。考虑修改一个字符的贡献,会使得所有以该字符为瓶颈的回文串增加长度,同时会使得原来所有最长回文串经过该位置的位置减少长度。换个视角,不妨通过二分+哈希分别预处理出以每个位置为回文中心的最长回文串长度、以及修改一个字符后的最长回文串长度,则对......
  • 无涯教程-Java - String substring(int beginIndex)函数
    从beginIndex索引处开始截取字符串。Stringsubstring-语法publicStringsubstring(intbeginIndex)这是参数的详细信息-beginIndex  -  包含开始索引。Stringsubstring-返回值指定的子字符串。Stringsubstring-示例importjava.io.*;publicclassTest......
  • 无涯教程-Java - String substring(int beginIndex, int endIndex)函数
    截取beginIndex索引开始到endIndex结束之间的字符串内容。Stringsubstring-语法这是此方法的语法-publicStringsubstring(intbeginIndex,intendIndex)这是参数的详细信息-beginIndex - 包含开始索引。endIndex   - 不包含结束索引。Stringsubstri......
  • sql中的substring()、to_char()、extract()、concat()等函数
    ERROR:functionpg_catalog.substring(timestampwithouttimezone,integer,integer)doesnotexistLINE1:SELECTu.username,l.description,l.ip,SUBSTRING(l.createdate,…^HINT:Nofunctionmatchesthegivennameandargumenttypes.Youmightneedtoadde......
  • Count Beautiful Substrings II
    CountBeautifulSubstringsIIYouaregivenastring s andapositiveinteger k.Let vowels and consonants bethenumberofvowelsandconsonantsinastring.Astringis beautiful if:vowels==consonants.(vowels*consonants)%k==0,inothert......
  • Java字符串分割[split()]和截取[substring()]
    字符串的分割:一般自字符串的分割常用的方法是java.lang包中的String.split()方法,返回是一个字符串数组。语法:publicString[]split(Stringregex,intlimit)参数:regex -- 正则表达式分隔符。limit --分割的份数。比如:需要分割字符串中的每个字符(空格也会被看做字符),split()中......
  • Solution - Hossam and (sub-)palindromic tree
    又名:《最近vjudge题全部罚坐》。唯一Trick:回文序列,就想区间dp!时间复杂度\(O(n^2)\)!如果是序列:\(f_{l,r}\)表示\([l,r]\)的最长回文子序列,\(f_{l,r}=\max(f_{l+1,r},f_{l,r-1},f_{l+1,r-1}+[s_l=s_r])\),\(s\)是字符串。很trivial。但是这是在......
  • MySQL SUBSTRING() 函数
    语法SUBSTRING(string,start,length)参数值参数必填描述string必需要从中提取的字符串start必需起始位置。可以是正数也可以是负数。如果是正数,此函数从字符串的开头提取。如果是负数,此函数从字符串的末尾提取;字符串索引从1开始length可选要提取的字......
  • js substring截取字符串,不信你看不懂,简单案例分享
     在JavaScript中,substring 方法用于截取字符串。它返回字符串的一个子集,即原始字符串中介于两个指定下标之间的字符。substring 方法的语法如下:str.substring(indexStart[,indexEnd])indexStart:必需的参数,表示要提取的第一个字符的下标(位置)。如果 indexStart 大于 ind......