题目描述
给定一个字符串str,如果可以在str的任意位置添加字符,请返回添加字符最少的情况下,让str整体都是回文字符串的一种结果。
解题思路
本题可以使用动态规划的思想,dp[i][j]表示子字符串(i,j)变成回文字符串需要添加的字符数,则有如下公式:
1. 如果str[i]==str[j]时,dp[i][j] = dp[i+1][j-1];
2. 如果str[I]!=str[j]时,dp[i][j] = min{dp[i][j-1],dp[i+1][j]} + 1;
此时dp[0][len-1]则为需要添加的最少字符数。
接下来构建回文的结果,char[] result,我们定义ni=0,nj=str.length+dp[0][len-1].(及原数组长度加上需要添加的字符数)
1.如果str[I] == str[j],则result[ni++] = str[I],result[nj--]= str[j];
2.如果str[I]!=str[j],则判断dp[i+1][j] 和 dp[i][j-1]的大小,dp[i+1][j] > dp[i][j-1]时result[ni++]=str[j],result[nj--]=str[j];dp[i+1][j] <= dp[i][j-1]时result[ni++]=str[i],result[nj--]=str[i]
最终返回result.
代码如下
public static String getResult(String str) {
char[] chars = str.toCharArray();
int len = chars.length;
int[][] dp = new int[len+1][len+1];
for(int i=1;i<=len;i++) {
for (int j=i-1;j>=1;j--) {
if(chars[i-1] == chars[j-1]) {
if (i>j+2){
dp[j][i] = dp[j+1][i-1];
}
} else {
dp[j][i] = Math.min(dp[j+1][i],dp[j][i-1]) + 1;
}
}
}
int addLen = dp[1][len];
char[] res = new char[len + addLen];
int i = 0,ni = 0;
int j = len-1,nj = len+addLen-1;
while(ni <= nj){
if(chars[i] == chars[j]) {
res[ni++] = chars[i++];
res[nj--] = chars[j--];
} else {
if (dp[i+1][j] > dp[i+2][j+1]) {
res[ni++] = chars[i];
res[nj--] = chars[i];
i++;
} else {
res[ni++] = chars[j];
res[nj--] = chars[j];
j--;
}
}
}
return String.valueOf(res);
}