LeetCode.5-最长回文子串-中心扩散法(Swift)

118 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情 。如果哪里写的不对,请大家评论批评。

希望往后的日子,可以每天坚持一个算法,最近发现一个有意思的事情,LeetCode中等难度的题,也不简单,暴力算法固然能解决问题,但是从时间复杂度和空间复杂度上肯定达不到要求。

最长回文子

题目

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。

示例 1

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

示例 2

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

分析

中心扩散法(双指针)

为什么会是双指针的?

在回文有两种情况

一种是121这种回文奇数长度的回文,假设指针是i,判断回文就需要i-1==i+1来依次寻找

另一种是1221这种偶数的回文,这种就需要ii+1两个指针,先判断i==i+1然后再判断i-1==i+1+1依次寻找

看图之后你会发现,其实最后都是需要两个指针,向外扩散去寻找是否相等,奇数如果想和偶数一样先判断是否相等,其实可以先和自身对比一下,伪代码:

//奇数
if (list[i] == list[i]){
    L = i - 1
    R = i + 1
}
// 偶数
if (list[i] == list[i+1]){
    L = i - 1
    R = i + 1
}

简单图解

  • 奇数寻找

最长回文子串.drawio (1).png

  • 偶数寻找

最长回文子串.drawio (2).png

代码

双指针

class Solution {
    func longestPalindrome(_ s: String) -> String {
        if s.isEmpty {
            return ""
        }

        var L = 0
        var R = 0
        let chars = Array(s)
        for (i, _) in chars.enumerated() {
            let unevenL = palindrome(chars, i, i)
            let evenL = palindrome(chars, i, i+1)

            let MaxLen = max(unevenL, evenL)
            if MaxLen > R - L + 1 {
                L = i - (MaxLen - 1)/2
                R = i + MaxLen/2
            }
        }
        return String(chars[L...R])
    }
    
    func palindrome(_ s: [Character], _ l: Int, _ r: Int) -> Int {
        var L = l
        var R = r
        while L >= 0 && R < s.count && s[L] == s[R] {
            L -= 1
            R += 1
        }
        return R - L - 1
    }
}
class Solution {
    func longestPalindrome(_ s: String) -> String {
        let chars = Array<Character>(s)
        let length = chars.count
        guard length > 0 else {
            return ""
        }
        //创建一个,元素值重复,个数固定的数组
        var isPalidromeMatrix = Array(repeating: Array(repeating: false, count : length), count : length)
        
        var maxLength = 0
        var maxStartIndex = 0
        
        for palidromeLength in 1 ... length {
            for startIndex in 0 ... length - palidromeLength {
                let endIndex = startIndex + palidromeLength - 1
                var isPalidrome = false
                
                if palidromeLength == 1 {
                    isPalidrome = true
                } else if palidromeLength == 2 {
                    isPalidrome = chars[startIndex] == chars[endIndex]
                } else {
                    isPalidrome = chars[startIndex] == chars[endIndex] && isPalidromeMatrix[startIndex + 1][endIndex - 1]
                }
                
                if isPalidrome {
                    isPalidromeMatrix[startIndex][endIndex] = true
                    
                    if palidromeLength > maxLength {
                        maxStartIndex = startIndex
                        maxLength = palidromeLength
                    }
                }
            }
        }
        
        return String(chars[maxStartIndex...maxStartIndex + maxLength - 1])
    }
}