LeetCode.5-最长回文子串-动态规划(Swift)

199 阅读2分钟

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

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

最长回文子

题目

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

示例 1

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

示例 2

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

分析

边界条件

  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 
}

先确定需要两个指针,当x==y是单个字符,肯定属于回文子串,类似中心扩展,那么需要下标x+1==y-1相等才能满足回文

动态规划

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

  1. 需要一个二维数组来记录数据对比的结果,
  2. 如图,假设横向是x,纵向是y
  3. 下标x==y的时候,值肯定是相等的,所以对角线值是true
  4. 图中是按照y轴开始写入的, 当然写二维数组的上半部分,效果是一样的
  5. 因为把对角线已经写入true了,下面写入的部分到对角线就可以停止了
  6. 两个循环,因为0,0``1,1都已经写入值了,我们可以直接从1,0开始

图解

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

代码

func longestPalindrome(_ s: String) -> String {
        let chars = Array<Character>(s)
        let length = chars.count
        guard length > 1 else {
            return ""
        }
        //定义一个二维矩阵
        var palidromeMatrix = Array(repeating: Array(repeating: false, count : length), count : length)

        // 对角线肯定是true
        for i in 0..<length {
            palidromeMatrix[i][i] = true
        }

        var maxLength = 1
        var startIndex = 0

        for y in 1 ..< length {
            for x in 0 ..< y {
                if chars[y] != chars[x] {
                    palidromeMatrix[y][x] = false
                }else{
                    if y - x < 3 {
                        palidromeMatrix[y][x] = true
                    }else{
                        palidromeMatrix[y][x] = palidromeMatrix[y-1][x+1]
                    }
                }
                if (palidromeMatrix[y][x] && y - x + 1 > maxLength) {
                    maxLength = y - x + 1;
                    // 更新回文串下标的起始位置
                    startIndex = x;
                }

            }
        }
        return String(chars[startIndex...startIndex + maxLength - 1])
    }