不忘初心,砥砺前行
题目要求
给定一个字符串,求出它的最长回文子串的长度
题目分析
常规思路
分析题目可知,该题可以抓换成两个问题如下
判断是否是回文
对于一个回文字符串,我们可以很轻易的找到其中的规律就是首尾逐个字符进行遍历是相同的字符因此我们可以定义两个指针指向首和尾,进行遍历比较,如果遇见不相同的则返回false
代码
func IsPalindrome_one(str string) bool {
// 非法输入
if len(str) == 0 {
return false
}
// 定义两个指针
right := len(str) - 1
left := 0
for i := left; i < len(str)/2; i++ {
if str[i] != str[right] {
return false
}
right--
}
return true
}
寻找子串
对于一个字符串,举例abcd,可以从a进行遍历,分别追加后面的字符形成子串,然后以b进行遍历。代码如下
// 获取所有的字串
func getAllSubstring(str string) (re []string) {
for i := 0; i < len(str); i++ {
j := len(str)
for j = len(str); j > i; j-- {
re = append(re, str[i:j])
}
}
return re
}
完整代码
// 常规解法
func LookPanlind_one(str string) string {
// 找到该字符串的所有字串存放到字符串数组
re := getAllSubstring(str)
max := 0
sign := 0
// 遍历 数组
for i := 0; i < len(re); i++ {
if IsPalindrome_one(re[i]) {
if max < len(re[i]) {
max = len(re[i])
sign = i
}
}
}
return re[sign]
}
// 获取所有的字串
func getAllSubstring(str string) (re []string) {
for i := 0; i < len(str); i++ {
j := len(str)
for j = len(str); j > i; j-- {
re = append(re, str[i:j])
}
}
return re
}
// 判断是否是回文字符串
func IsPalindrome_one(str string) bool {
// 非法输入
if len(str) == 0 {
return false
}
// 定义两个指针
right := len(str) - 1
left := 0
for i := left; i < len(str)/2; i++ {
if str[i] != str[right] {
return false
}
right--
}
return true
}
虽然可以求出最终结果,但是这样的方法过于复杂,我们是将所有的字串进行查找出后进行循环判断,增加了代码的时间复杂度,下面介绍中心扩展法
中心扩展法
对于一个回文字符串,找到一个中心位置,不断向外扩展,所对应的字符都是相同的,举例“aba”,以b为中心,判断出a和a相同,因此对于一个字符串,只需要找到一个中心轴,判断其两边的字符的相等情况即可。
// 中心扩展法
func LookPanlind_two(str string) (s string) {
i, j, max, c := 0, 0, 0, 0
for i = 0; i < len(str); i++ {
// 回文长度为奇数
for j = 0; (i+j) < len(str) && (i-j) >= 0; j++ {
if str[i-j] != str[i+j] {
break
}
c = 2*j + 1
}
if max < c {
s = str[(i - j + 1):(i + j)]
println("奇数", s)
max = c
}
// 回文长度为偶数
for j = 0; (i+j+1) < len(str) && (i-j) >= 0; j++ {
if str[i-j] != str[i+j+1] {
break
}
c = 2*j + 2
}
if max < c {
s = str[(i - j + 1):(i + j + 1)]
println("偶数", s)
max = c
}
}
return s
}
代码分析
对于寻找奇数的回文,扩展根据i为中心轴进行左右指针的移动,因此我们可以定义一个j初始化为0,i+j则为当前或者下一个字符,i-j则为当前或者前一个字符,然后对字符进行比较。c用于表示临时的回文长度,求出后将之与max进行比对.对于找到最长的字符串,仍可利用切片的性质,这里需要注意的是对于切片为前者包含,后者不包含,但是由于进入if循环后j多+1了一次,因此i-j便是多减去了一个1,所以要+1,后者的由于j多加1刚好满足切片的条件。
for j = 0; (i+j) < len(str) && (i-j) >= 0; j++ {
if str[i-j] != str[i+j] {
break
}
c = 2*j + 1
}
if max < c {
s = str[(i - j + 1):(i + j)]
println("奇数", s)
max = c
}
更多详细代码可以公众号后台回复关键词github,如果觉得有益,欢迎点个星
作者 | 陌无崖
转载请联系授权
END
今日推荐阅读
RabbitMQ系列笔记广播模式和路由模式
RabbitMQ系列笔记入门篇
RabbitMQ系列笔记work模式
RabbitMQ系列笔记work模式
protoc语法详解及结合grpc定义服务
Golang中Model的使用
基于Nginx和Consul构建高可用及自动发现的Docker服务架构
▼关注我,一起成长
主要分享 学习心得、笔记、随笔▼