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)的主要内容,如果未能解决你的问题,请参考以下文章

力扣5-最长回文子串-(Manacher算法)

力扣5. 最长回文子串

精选力扣500题 第30题 LeetCode 5. 最长回文子串c++ / java 详细题解

力扣5. 最长回文子串 中心拓展算法+动态规划法

力扣5. 最长回文子串 中心拓展算法+动态规划法

leetcode 5 最长回文子串