1.硬币问题 377. 组合总和 Ⅳ
public int ways(int []nums,int target){ int[]dp=new int[target+1]; //dp[i]表示和为i有多少种组合 dp[0]=1; for(int i=0;i<=target;i++) for(int n:nums){ if(n+i<=target) dp[n+i]+=dp[i]; } return dp[target]; }
简单递归
int count(int[]nums,int sum,int tar){ int res=0; if(sum<tar){ for(int i:nums) res+=count(nums,sum+i,tar); }else if(sum==tar) return 1; else return 0; return res; }
2.LCS
int lcs(String a,String b){ int lena=a.length(),lenb=b.length(); int [][]dp=new int[lena+1][lenb+1]; //dp[i][j]表示a的前i个和b的前j个的LCS for(int i=1;i<=lena;i++) for(int j=1;j<=lenb;j++) if(a.charAt(i-1)==b.charAt(j-1)) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=Math.max(dp[i][j-1], dp[i-1][j]); return dp[lena][lenb]; }
3.0-1背包
public int ways(int c){ int packets=w.length; int [][]dp=new int[packets+1][c+1]; for(int i=1;i<=packets;i++) for(int j=0;j<=c;j++){ if(j==0) dp[i][j]=0; else if(j>=w[i-1]){ dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-w[i-1]]+p[i-1]); }else dp[i][j]=dp[i-1][j]; } return dp[packets][c]; }
空间优化后:
public int ways2(int c){ int packets=w.length; int []dp=new int[c+1]; for(int i=1;i<=packets;i++) for(int j=c;j>=0;j--) if(j>=w[i-1]) dp[j]=Math.max(dp[j], dp[j-w[i-1]]+p[i-1]); return dp[c]; }
简单递归
public int solve(int i,int n,int j,int max){ if(i<n){ if(j>=w[i]){ return Math.max(solve(i+1,n,j-w[i],max+p[i]),solve(i+1,n,j,max)); }else{ return solve(i+1,n,j,max); } }else return max; }
3.多重背包
public int packetK(int c){ int [][]dp=new int[w.length+1][c+1]; for(int i=1;i<=w.length;i++) for(int j=0;j<=c;j++) if(j==0) dp[i][j]=0; else if(j<w[i-1]) dp[i][j]=dp[i-1][j]; else{ for(int k=1;k*w[i-1]<=j;k++){ int tmp=Math.max(dp[i-1][j], dp[i-1][j-k*w[i-1]]+k*p[i-1]); dp[i][j]=dp[i][j]<tmp?tmp:dp[i][j]; } } return dp[w.length][c]; }
4.最长非降序子序列 类似 300. 最长上升子序列
//最长非降序子数列 public int MaxUnDESCSub(int []nums){ int []dp=new int[nums.length]; //dp[i]为0..i不降序的最大字串长度 Arrays.fill(dp, 1); for(int i=1;i<nums.length;i++){ for(int j=0;j<i;j++){ if(nums[i]>=nums[j]&&dp[i]<=dp[j]) dp[i]=dp[j]+1; } } Arrays.sort(dp); return dp[nums.length-1]; }
5.爬台阶
public int ways(int n){ int []dp=new int[n+1]; dp[1]=1;dp[2]=1; for(int i=3;i<=n;i++) dp[i]=dp[i-1]+dp[i-2]; return dp[n]; }
6.平衡字串(前缀思想
public int maxBlancedSub(String s){ /* *前缀和思想 连续性 *dp[i]表示前i个数 */ int len=s.length(); int []dp=new int[len+1]; for(int i=1;i<=len;i++) if(s.charAt(i-1)=='0') dp[i]=dp[i-1]-1; else dp[i]=dp[i-1]+1; HashMap<Integer,Integer>map=new HashMap<>(); int max=0,begin=0; for(int i=1;i<=len;i++){ if(map.containsKey(dp[i])) begin=map.get(dp[i]); else map.put(dp[i], i); if(dp[i]==dp[begin]&&i-begin>max) max=i-begin; } return max; }
7.图论问题 leetcode787
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) { int [][]dp=new int[n][k+1]; int [][]f=new int[n][n]; for(int i=0;i<n;i++){ Arrays.fill(dp[i], Integer.MAX_VALUE); Arrays.fill(f[i], -1); f[i][i]=0; } for(int i=0;i<flights.length;i++) f[flights[i][0]][flights[i][1]]=flights[i][2]; /* * dp[i][j] 到达i站 且经过站数为j 的最小cost*/ for(int j=0;j<=k;j++){ for(int i=0;i<n;i++){ if(i==src) dp[i][j]=0; else if(j==0&&f[src][i]>=0) dp[i][j]=f[src][i]; else if(j>0){ for(int m=0;m<n;m++) if(m!=i&&f[m][i]>0&&dp[m][j-1]!=Integer.MAX_VALUE) dp[i][j]=Math.min(dp[m][j-1]+f[m][i], dp[i][j]); } } } Arrays.sort(dp[dst]); if(dp[dst][0]!=Integer.MAX_VALUE) return dp[dst][0]; return -1; }
public int numTrees(int n) { int []dp=new int[n+1]; for(int i=1;i<=n;i++){ if(i==1||i==2) dp[i]=i; else{ for(int j=1;j<=i;j++) if(j>1&&j<i)//有左子树和右子树 dp[i]+=dp[j-1]*dp[i-j]; else if(j==1)//只有右子树 dp[i]+=dp[i-j]; else dp[i]+=dp[j-1]; } } return dp[n]; }