动态规划
动态规划的思想就是,将一个大问题分解为规模更小的问题,这个小问题的解一定是可以直接求出的,并且原问题的最优解包含子问题的最优解。也就是说分治算法+贪婪算法!
寻找回文串
给定一个字符串s,找出s中的最大回文串。如 输入:s=“babad” 输出:“bab”(“aba”也可作为输出)
算法解析
设置一个二维数组 dp[i][j] ,存储字符串s的下标 i 到 j 之间的最大回文串长度。数组长度为dp[s.length()][s.length()]
- 基础小问题的解:
d
p
[
i
]
[
i
]
=
1
;
dp[i][i]=1;
dp[i][i]=1;
d
p
[
i
]
[
i
+
1
]
=
{
2
if?s(i)?==?s(i+1)?
1
if?s(i)?!=?s(i+1)?
dp[i][i+1]= \begin{cases} 2& \text{if s(i) == s(i+1) }\\ 1& \text{if s(i) != s(i+1) } \end{cases}
dp[i][i+1]={21?if?s(i)?==?s(i+1)?if?s(i)?!=?s(i+1)?? - 迭代关系:
d
p
[
i
]
[
j
]
=
{
d
p
[
i
+
1
]
[
j
?
1
]
+
2
,
if?
s
(
i
)
=
=
s
(
i
+
1
)
?and?
d
p
[
i
+
1
]
[
j
?
1
]
=
j
?
i
?
1
m
a
x
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
?
1
]
)
,
if?
s
(
i
)
!
=
s
(
i
+
1
)
?
dp[i][j]= \begin{cases} dp[i+1][j-1]+2, & \text {if $s(i) == s(i+1)$ and $dp[i+1][j-1]=j-i-1$} \\ max(dp[i+1][j],dp[i][j-1]), & \text{if $s(i) != s(i+1)$ } \end{cases}
dp[i][j]={dp[i+1][j?1]+2,max(dp[i+1][j],dp[i][j?1]),?if?s(i)==s(i+1)?and?dp[i+1][j?1]=j?i?1if?s(i)!=s(i+1)?? PS:
d
p
[
i
+
1
]
[
j
?
1
]
=
(
j
?
1
)
?
(
i
+
1
)
+
1
=
j
?
i
?
1
dp[i+1][j-1]=(j-1)-(i+1)+1=j-i-1
dp[i+1][j?1]=(j?1)?(i+1)+1=j?i?1 即保证 i+1 , j-1 之间的字符都满足回文要求。
java 代码实现如下:
class Solution {
public String longestPalindrome(String s) {
if(s.length()==1){
return s;
}
int[][] dp=new int[s.length()][s.length()];
for(int i=s.length()-1;i>=0;i--){
dp[i][i]=1;
if (i<s.length()-1){
if(s.charAt(i)==s.charAt(i+1)){
dp[i][i+1]=2;
}else{
dp[i][i+1]=1;
}
System.out.print(dp[i][i+1]);
}
for(int j=i+2;j<s.length();j++){
if(s.charAt(i)==s.charAt(j) && dp[i+1][j-1]==j-i-1){
dp[i][j]=dp[i+1][j-1]+2;
}else{
if(dp[i+1][j]>dp[i][j-1]){
dp[i][j]=dp[i+1][j];
}else{
dp[i][j]=dp[i][j-1];
}
}
}
}
int v=dp[0][s.length()-1];
if(v==1){
return String.valueOf(s.charAt(0));
}else{
String res="";
for(int i=0;i<s.length();i++){
for(int j=i+1;j<s.length();j++){
if(dp[i][j]==v && (j-i+1)==v){
res=s.substring(i,j+1);
}
}
}
return res;
}
}
}
|