Code34 添加字符变回文

235 阅读1分钟

题目描述

  • 给定一个字符串,如果可以在字符串任意位置添加字符,最少添加几个能让字符串整体都是回文串。

举例

  • abcd -> 3 (abcdcba)
  • ab -> 1 (aba bab)
  • a -> 0

思路

  • 范围上的尝试模型, 从L -> R 上需要添加几个字符
  • 分情况讨论:
    1. 只有一个字符: 0
    1. 有两个字符: 相等就是 0 不相等就是 1
    1. 对于任意一个普遍位置:
    • 3.1 [i...j] 位置, 先使得 [i...j-1] 位置变为回文,再在左边填一个[j]
    •    举例:  abac -> 先让aba 变成回文,在添加一个c 变成 cabac
      
    • 3.2 [i...j] 位置, 先使得 [i+1...j] 位置变为回文,再在右边填一个[i]
    •    举例:  daba -> 先让aba 变成回文,在添加一个c 变成 dabad
      
    • 3.3 [i...j] 位置 只有当 [i] == [j] 时 直接变为[i+1...j-1]
    •    举例:  acba -> 让 cb 变成回文  -> acbca
      
    • 所以每个位置只依赖自己 左边的、下边的,左下角的格子

code

public class Code34 {
    public static int addCharToPalindrome(String s) {
        if (s == null || s.length() <= 0) {
            return 0;
        }
        char[] str = s.toCharArray();
        int N = str.length;
        int[][] dp = new int[N][N];
        // 先填对角线 都是0 (系统默认是0 所以不用填)
        // 再填第二条对角线
        for (int i = N - 2; i >= 0; i--) {
            dp[i][i + 1] = str[i] == str[i + 1] ? 0 : 1;
        }
        // 处理每一个普遍位置 从下往上 从左往右
        for (int i = N - 3; i >= 0; i--) {
            for (int j = i + 2; j < N; j++) {
                if (str[i] == str[j]) {
                    dp[i][j] = dp[i + 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) + 1;
                }
            }
        }
        return dp[0][N - 1];
    }

    public static void main(String[] args) {
        System.out.println(addCharToPalindrome("abcde"));
        System.out.println(addCharToPalindrome("ab"));
        System.out.println(addCharToPalindrome("q"));
    }
}