区间型动态规划判断:
1.去头/去尾
2.二分
667. Longest Palindromic Subsequence
https://www.lintcode.com/problem/longest-palindromic-subsequence/description?_from=ladder&&fromId=16
public class Solution { /** * @param s: the maximum length of s is 1000 * @return: the longest palindromic subsequence's length */ public int longestPalindromeSubseq(String ss) { // write your code here if(ss==null || ss.length()==0) return 0; char[] s = ss.toCharArray(); int n = s.length; int f[][] = new int[n][n]; for(int i=0;i<n;i++){ f[i][i] = 1; } for(int i=0;i<n-1;i++){ if(s[i]==s[i+1]){ f[i][i+1] = 2; }else{ f[i][i+1]=1; } } for(int len=3;len<=n;len++){ for(int i=0;i<n;i++){ int j = i+len-1; if(j>=n){ break; } f[i][j]= Math.max(f[i+1][j],f[i][j-1]); if(s[i]==s[j]){ f[i][j] = Math.max(f[i][j],f[i+1][j-1]+2); } } } return f[0][n-1]; } }
记忆化搜索:递归实现
public class Solution { /** * @param s: the maximum length of s is 1000 * @return: the longest palindromic subsequence's length */ int[][]f; public int longestPalindromeSubseq(String ss) { // write your code here if(ss==null || ss.length()==0) return 0; char[] s = ss.toCharArray(); int n = s.length; f = new int[n][n]; for(int i=0;i<n;i++) for(int j=0;j<n;j++){ f[i][j] = -1; } calc(s,0,n-1); return f[0][n-1]; } public void calc(char[] s,int i,int j){ //important if(f[i][j]!=-1){ return; } //initialize if(i==j){ f[i][j]=1; return; } if(j-i==1){ if(s[i]==s[j]){ f[i][j]=2; }else{ f[i][j]=1; } return; } calc(s,i+1,j); calc(s,i,j-1); calc(s,i+1,j-1); f[i][j]= Math.max(f[i+1][j],f[i][j-1]); if(s[i]==s[j]){ f[i][j] = Math.max(f[i][j],f[i+1][j-1]+2); } return; } }
396. Coins in a Line III
思路:f[i][j]是指先手面对 i~j 的区间能取得的最大效益
https://www.lintcode.com/problem/coins-in-a-line-iii/description?_from=ladder&&fromId=16
public class Solution { /** * @param values: a vector of integers * @return: a boolean which equals to true if the first player will win */ public boolean firstWillWin(int[] values) { // write your code here if(values==null || values.length==0){ return true; } int n = values.length; int[][] f = new int[n][n]; for(int i=0;i<n;i++){ f[i][i]= values[i]; } for(int len =2;len<=n;len++){ for(int i=0;i<n;i++){ int j = i+len-1; if(j>=n){ break; } f[i][j] = Math.max(values[j]-f[i][j-1],values[i]-f[i+1][j]); } } return f[0][n-1]>=0; } }
430. Scramble String
思路:f[i][j][w] 是指 s1以i为起始w长度的字符串 和 s2以j为起始w长度的字符串 是否可以是攀爬字符串
https://www.lintcode.com/problem/scramble-string/description?_from=ladder&&fromId=16
public class Solution { /** * @param s1: A string * @param s2: Another string * @return: whether s2 is a scrambled string of s1 */ public boolean isScramble(String s1, String s2) { // write your code here if(s1 == null && s2!=null){ return false; } if(s1!=null && s2==null){ return false; } if(s1.length()!=s2.length()){ return false; } int n = s1.length(); boolean[][][] f = new boolean[n][n][n+1]; for(int i=0;i<n;i++){ for(int j =0;j<n;j++){ f[i][j][1]= s1.charAt(i)==s2.charAt(j)? true:false; } } for(int len=2;len<=n;len++){ for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ f[i][j][len] = false; for(int w=1;w<len;w++){ if(i+w<n && j+w<n && f[i][j][w] && f[i+w][j+w][len-w]){ f[i][j][len] = true; break; } if(i+w<n && j+len-w<n && f[i][j+len-w][w] && f[i+w][j][len-w]){ f[i][j][len] = true; break; } } } } } return f[0][0][n]; } }