Dynamic Programming
通过循环做出每一步的最优解从而自底向上的得出对问题的整体最优解。
动态规划三步骤
确定定义——> 找初始值——> 思考关系——> 代码
例:给你一个字符串 s
,找到 s
中最长的回文子串。
输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
1.确定定义
求字符串中的最长回文子串,就设dp[i][j]为子串s.substring(i,j)是否为回文串
2.找初始值
所有长度为1的子串都是回文串,dp[i][i] = true.
3.思考关系
只有当子串s.substring(i+1, j-1)是回文串,并且s的第i和第j个字母相同时,s.substring(i, j)才会是回文串。
dp[i][j] = dp[i+1][j-1] && (s.charAt(i) == s.charAt(j))
要找s中最长的子回文串,那么就是所有dp[i][j]=true中j-i+1(子串长度)的最大值。
dp[i][j]为false的情况:该子串不是回文串;i>j
4.代码
public class Solution{
public String longestPalindrome(String s){
int len = s.length();
if(len < 2)
return s;
boolean[][] dp = new boolean[len][len];
//initialization
for(int i=0; i<len; ++i){
dp[i][i] = true;
}
//dp
//自底向上,从子串长度为2开始
for(int k=1; k<len; ++k){
//枚举左边界
for(int i=0; i<len; ++i){
//确定右边界
int j=i+k;
if(j >= len)
break;
//推导
if((k==1 || dp[i+1][j-1]) && s.charAt(i)==s.charAt(j)){
dp[i][j] = true;
}else{
dp[i][j] = false;
}
}
}
//find max
int maxLen = 1;
int low=0, high=1;
for(int i=0; i<len; ++i){
for(int j=i; j<len; ++j){
if(dp[i][j] && maxLen < j-i+1){
maxLen = j-i+1;
low = i;
high = j+1;
}
}
}
return s.substring(low, high);
}
}