• [LeetCode] 5. Longest Palindromic Substring(最长回文子串)


    Description

    Given a string s, return the longest palindromic substring in s.
    给定一字符串 s,返回其最长回文子串。

    Examples

    Example 1

    Input: s = "babad"
    Output: "bab"
    Note: "aba" is also a valid answer.
    

    Example 2

    Input: s = "cbbd"
    Output: "bb"
    

    Example 3

    Input: s = "a"
    Output: "a"
    

    Example 4

    Input: s = "ac"
    Output: "a"
    

    Constraints

    • 1 <= s.length <= 1000
    • s consist of only digits and English letters (lower-case and/or upper-case),

    Hints

    1. How can we reuse a previously computed palindrome to compute a larger palindrome?
      如何利用已确定的回文子串确定更大的回文子串?

    2. If "aba" is a palindrome, is "xabax" and palindrome? Similarly is "xabay" a palindrome?
      如果 "aba" 是回文的,那么 "xabax" 是回文的吗?类似地,"xabay" 呢?

    3. Complexity based hint:
      If we use brute-force and check whether for every start and end position a substring is a palindrome we have O(n^2) start - end pairs and O(n) palindromic checks. Can we reduce the time for palindromic checks to O(1) by reusing some previous computation.
      更基础的提示:
      如果使用暴力搜索,检查每一个 start 和 end 位置组成的子串是否回文,则要进行 (O(n^2)) 次检查,每次检查花费 (O(n)) 时间。能否通过利用之前的结果,将回文检查的时间复杂度降至 (O(1))

    Solution

    根据提示的指示,我们的目标是将回文检查的时间复杂度降至 (O(1)),这里采取的策略是边扩展边检查。对于每个字符,使用 (O(N)) 时间扩展,同时完成回文检查。代码如下:

    class Solution {
        private var result = ""
    
        fun longestPalindrome(s: String): String {
            if (s.length < 2) {
                return s
            }
            if (s.length == 2) {
                return if (s[0] == s[1]) s else s.substring(1)
            }
    
            for (i in s.indices) {
                updatePalindrome(s, i)
            }
    
            return result
        }
    
        private fun updatePalindrome(s: String, startIndex: Int) {
            updatePalindromeOdd(s, startIndex)
            updatePalindromeEven(s, startIndex - 1, startIndex)
            updatePalindromeEven(s, startIndex, startIndex + 1)
        }
    
        private fun updatePalindromeOdd(s: String, startIndex: Int) {
            if (result.isEmpty()) {
                result = s.substring(startIndex, startIndex + 1)
            }
            doUpdate(s, startIndex - 1, startIndex + 1)
        }
    
        private fun updatePalindromeEven(s: String, leftBound: Int, rightBound: Int) {
            doUpdate(s, leftBound, rightBound)
        }
    
        private fun doUpdate(s: String, leftBound: Int, rightBound: Int) {
            var left = leftBound
            var right = rightBound
            while (left in s.indices && right in s.indices) {
                if (s[left] != s[right]) {
                    break
                }
                if ((right - left + 1) > result.length) {
                    result = s.substring(left, right + 1)
                }
                left--
                right++
            }
        }
    }
    

    实际上,奇数长度和偶数长度的情况可以合并以简化代码,简化后的代码如下:

    class Solution {
        private var result = ""
    
        fun longestPalindrome(s: String): String {
            if (s.length < 2) {
                return s
            }
            if (s.length == 2) {
                return if (s[0] == s[1]) s else s.substring(1)
            }
    
            for (i in s.indices) {
                updatePalindrome(s, i)
            }
    
            return result
        }
    
        private fun updatePalindrome(s: String, startIndex: Int) {
            // 奇数长度情况
            doUpdate(s, startIndex, startIndex)
            // 偶数长度情况
            doUpdate(s, startIndex - 1, startIndex)
            doUpdate(s, startIndex, startIndex + 1)
        }
    
        private fun doUpdate(s: String, leftBound: Int, rightBound: Int) {
            var left = leftBound
            var right = rightBound
            while (left in s.indices && right in s.indices) {
                if (s[left] != s[right]) {
                    break
                }
                if ((right - left + 1) > result.length) {
                    result = s.substring(left, right + 1)
                }
                left--
                right++
            }
        }
    }
    
  • 相关阅读:
    laravel passport 全局捕获 401 ,返回数据给前台
    服务器上每次执行git pull,都提示输入用户名和密码
    jQuery-File-Upload 使用,jQuery-File-Upload上传插件
    Java返回结果封装,SpringBoot返回结果封装
    Java Spring文件上传,Java文件上传,Java通用文件上传
    Mdb文件工具类,UCanAccess使用,Access数据库操作
    Access MDB文件解析查询,Access数据库解析工具类MdbUtils
    jquery easyui combogrid Uncaught TypeError:Cannot read property
    soap调用Jar包冲突,SOAPMessageContext
    js打开新窗口,js打开居中窗口,js打开自定义窗口
  • 原文地址:https://www.cnblogs.com/zhongju/p/14132156.html
Copyright © 2020-2023  润新知