【算法题】最长回文串

题目

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。

在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

注意:
假设字符串的长度不会超过 1010。

示例 1:

输入:
"abccccdd"

输出:
7

解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

解题思路
首先,回文串基本有以下两种形式:

ABA(两边出现的字符串成对出现,并可存在也仅能存在一个中间字符)
AA(只有两边成对出现的字符)

可以看到回文串形式都需要两边出现成对的字符,因此,在本题中,应尽可能把所有偶数次数的字符取出来(例如,有3个相同的字符则取完偶数2个字符),然后再根据由所有偶数次字符组成的回文串长度来判断是否能组成:ABA,这种含有中间字符形式的回文串,即可得到在最后答案。

实现思路

  1. 把输入字符串所有字符计次保存进hash表。
  2. 遍历整个hash表存储的所有值,把偶数部分取出来,作为累加长度
  3. 遍历完hash表后,判断当前累加的长度是否等于原字符串长度,如果小于原字符串长度,则证明还存在奇数次的字符未计入回文串中,这时候则可随意取任意一个奇数字符组成:ABA,这种存在中间字符的回文串,即最长回文串长度+1,即可得到最后结果。

小技巧

  1. 小写字母’z’跟大写字母起始’A’之间的Ascii码相差57(具体忘记的可直接用下面提供的代码输出验证),因此,所有小写、大写英文字母最多占用58个位置,所以,我们可以声明一个58大小的Int型数组作为一个计算字母出现次数的hash表使用。
  2. 用位移运算符,先右移(>>)再左移(<<)结果等同于:(x / 2) * 2,可直接把数值中偶数部分取出来(例如:1001取出1000,9取出8)。这里看到有高手用更巧妙的方法,设数值为x:x - (x&1),即可得出偶数部分。

验证代码

func main() {
	fmt.Println('z' - 'A')
}

输入结果

57

解题代码

func longestPalindrome(s string) int {
    byteCount := make([]int, 58)
    for _, v := range s {
        byteCount[v - 'A']++
    }
    maxLen := 0
    for _, v := range byteCount {
        maxLen += (v >> 1) << 1 //或者写成v - (v & 1)这种效率更高的写法
    }
    if maxLen < len(s) {
        maxLen++
    }
    return maxLen
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值