5. 最长回文子串(LeetCode力扣算法 - java / rust)
Posted 二当家的白帽子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5. 最长回文子串(LeetCode力扣算法 - java / rust)相关的知识,希望对你有一定的参考价值。
5. 最长回文子串:
给你一个字符串 s,找到 s 中最长的回文子串。
样例 1:
输入:
s = "babad"
输出:
"bab"
解释:
"aba" 同样是符合题意的答案。
样例 2:
输入:
s = "cbbd"
输出:
"bb"
样例 3:
输入:
s = "a"
输出:
"a"
样例 4:
输入:
s = "ac"
输出:
"a"
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母(大写 和 / 或 小写)组成
原题传送门
题解
参照官方java题解做了一些修改,速度应该会快一些,并写了rust实现。
java
class Solution {
public String longestPalindrome(String s) {
// 在字符之间加入#号,使得字符数恒定变为奇数
StringBuilder temp = new StringBuilder("#");
for (int i = 0; i < s.length(); ++i) {
temp.append(s.charAt(i));
temp.append('#');
}
String ns = temp.toString();
// 最终结果的头尾下标
int start = 0, end = 0;
// 臂长缓存
int[] armLen = new int[ns.length()];
// 之前回文串的右边界,之前回文串的中位下标
int right = 0, mid = 0;
for (int i = 0; i < ns.length(); ++i) {
// 判断是否有过臂长缓存
int minArmLen;
if (right > i) {
int index = mid * 2 - i;
minArmLen = Math.min(armLen[index], right - i);
} else {
minArmLen = 0;
}
// 当前臂长
int curArmLen = expand(ns, i - minArmLen, i + minArmLen);
// 将当前臂长缓存
armLen[i] = curArmLen;
// 新的串超出之前子串的范围,用新的范围覆盖
if (i + curArmLen > right) {
mid = i;
right = i + curArmLen;
}
// 当前结果大于之前的结果
if (curArmLen * 2 + 1 > end - start) {
start = i - curArmLen;
end = i + curArmLen;
}
// 如果后面的剩下的字符不够最大臂长就没必要进行下去了
if (i + (end - start) / 2 >= ns.length()) {
break;
}
}
return s.substring(start / 2, end / 2);
}
private int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return (right - left - 2) / 2;
}
}
rust
impl Solution {
pub fn longest_palindrome(s: String) -> String {
let mut ns = Vec::with_capacity(s.len() << 1 + 1);
ns.push('#');
s.chars().for_each(|x| {
ns.push(x);
ns.push('#');
});
// 最终结果的头尾下标
let (mut start, mut end) = (0, 0);
// 臂长缓存
let mut arm_len = vec![0usize; ns.len()];
// 之前回文串的右边界,之前回文串的中位下标
let (mut right, mut mid) = (0, 0);
for i in (0..ns.len()) {
// 判断是否有过臂长缓存
let min_arm_len;
if right > i {
let index = mid * 2 - i;
min_arm_len = arm_len[index].min(right - i);
} else {
min_arm_len = 0;
}
// 当前臂长
let cur_arm_len = Solution::expand(&ns, i - min_arm_len, i + min_arm_len);
// 将当前臂长缓存
arm_len[i] = cur_arm_len;
// 新的串超出之前子串的范围,用新的范围覆盖
if (i + cur_arm_len > right) {
mid = i;
right = i + cur_arm_len;
}
// 当前结果大于之前的结果
if (cur_arm_len * 2 + 1 > end - start) {
start = i - cur_arm_len;
end = i + cur_arm_len;
}
// 如果后面的剩下的字符不够最大臂长就没必要进行下去了
if (i + (end - start) / 2 >= ns.len()) {
break;
}
}
return String::from(&s[start / 2..end / 2]);
}
fn expand(s: &Vec<char>, left: usize, right: usize) -> usize {
let mut left = left as i32;
let mut right = right;
while left >= 0 && right < s.len() && s[left as usize] == s[right] {
left -= 1;
right += 1;
}
return (right as i32 - left - 2) as usize / 2;
}
}
最后说两句
非常感谢你阅读本文章,如果你觉得本文对你有所帮助,请留下你的足迹,点个赞,留个言,多谢~
作者水平有限,如果文章内容有不准确的地方,请指正。
希望小伙伴们都能每天进步一点点。
本文由二当家的白帽子博客原创,转载请注明来源,谢谢~
以上是关于5. 最长回文子串(LeetCode力扣算法 - java / rust)的主要内容,如果未能解决你的问题,请参考以下文章