动态规划之最长回文子串

645 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

动态规划(Dynamic Programming)是一种分阶段求解决策问题的数学思想,它通过把原问题分解为简单的子问题来解决复杂问题。

最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd" 输出:"bb"

暴力解法

穷举字符串s的所有子串,然后遍历这些子串保存最长的回文串。

fun longestPalindrome(s: String): String {
    var result = ""
    var max = 0
    val len = s.length
    for (i in 0 until len) {
        for (j in i + 1..len) {
            val curr = s.substring(i, j)
            //isPalindromic()方法判断当前字符串是不是回文串
            if (isPalindromic(curr) && curr.length > max) {
                result = s.substring(i, j)
                max = Math.max(max, result.length)
            }
        }
    }
    return result
}

复杂度分析

  • 时间复杂度:O(n³),首先穷举子串需要两层 for 循环,循环里边判断是否为回文还需要一次循环,所以时间复杂度为 O(n³)。
  • 空间复杂度:O(1)。

动态规划

由于是找回文子串,所以会有一个开始位置start,结束位置end,我们定义一个二维数组dp,dp[start][end]=true表示s[start-end]是回文串,反之不是回文串。

对于长度为1的子串,它一定是一个回文串,对于长度大于等于2的子串,先判断start位置字符和end位置字符是否一致,不一致则不是回文串,否则继续判断start+1位置和end-1位置的字符,直到start和end相遇。

public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }
        int maxLen = 1;
        int begin = 0;
        boolean[][] dp = new boolean[len][len];
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        char[] charArray = s.toCharArray();
        for (int left = 2; left <= len; left++) {
            for (int start = 0; start < len; start++) {
                int end = left + start - 1;
                if (end >= len) {
                    break;
                }

                if (charArray[start] != charArray[end]) {
                    dp[start][end] = false;
                } else {
                    if (end - start < 3) {
                        dp[start][end] = true;
                    } else {
                        dp[start][end] = dp[start + 1][end - 1];
                    }
                }
                if (dp[start][end] && end - start + 1 > maxLen) {
                    maxLen = end - start + 1;
                    begin = start;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }
}

复杂度分析

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n^2),需要一个二维dp数组