携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情 。如果哪里写的不对,请大家评论批评。
希望往后的日子,可以每天坚持一个算法,最近发现一个有意思的事情,LeetCode中等难度的题,也不简单,暴力算法固然能解决问题,但是从时间复杂度和空间复杂度上肯定达不到要求。
最长回文子
题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1
输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。
示例 2
输入: s = "cbbd"
输出: "bb"
分析
边界条件
- 如果字符串长度为
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相等才能满足回文
动态规划
- 需要一个二维数组来记录数据对比的结果,
- 如图,假设横向是
x,纵向是y - 下标
x==y的时候,值肯定是相等的,所以对角线值是true - 图中是按照y轴开始写入的, 当然写二维数组的上半部分,效果是一样的
- 因为把对角线已经写入
true了,下面写入的部分到对角线就可以停止了 - 两个循环,因为
0,0``1,1都已经写入值了,我们可以直接从1,0开始
图解
代码
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])
}