1. 从暴力搜索到记忆搜索,再到动态规划
2. 找零问题
有数组penny,penny中所有的值都为正数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。
给定数组penny及它的大小(小于等于50),同时给定一个整数aim,请返回有多少种方法可以凑成aim。
测试样例:
[1,2,4],3,3
返回:2
import java.util.*;
//动态规划方法求解给定数额求找零方法的总数 是用空间换时间 时间复杂度为O(n*aim) 下一层方法总是枚举上一层的方法
public class Exchange {
public int countWays(int[] penny, int n, int aim) {
int[] dp=new int[aim+1];
dp[0]=1;//得到0值的方法对任何面值的组合来说都只有一种
for(int i=0;i<n;i++){
for(int j=penny[i];j<=aim;j++){
dp[j]+=dp[j-penny[i]];
}
}
return dp[aim];
}
}
3. 台阶问题
有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。
测试样例:
1
返回:1
import java.util.*;
//每次只能走1或者2步,求走完n个台阶的方法数 倒推使用f(i)=f(i-1)+f(i-2)的方法
public class GoUpstairs {
public int countWays(int n) {
/*if(n<1){
return 0;
}
if(n==1||n==2){
return n;
}
return (count(n-1)+count(n-2))%1000000007;
*/ //为什么数组越界?
int[] res=new int[300030];//大小如何确定的?
res[0]=1;
for(int i=1;i<=n;i++){
res[i]=((i>=1?res[i-1]:0)+(i>=2?res[i-2]:0))%1000000007;
}
return res[n];
}
}
4. 格子最短路径问题
import java.util.*;
//格子最短路径求解
public class MinimumPath {
public int getMin(int[][] map, int n, int m) {
int[][] dp=new int[n][m];
dp[0][0]=map[0][0];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(i==0&&j==0){
continue;
}
dp[i][j]=map[i][j]+Math.min((i>=1?dp[i-1][j]:dp[0][j-1]),(j>=1?dp[i][j-1]:dp[i-1][0]));
}
}
return dp[n-1][m-1];
}
}
5. LIS最大递增子序列
import java.util.*;
//数组最长上升自序列问题
public class LongestIncreasingSubsequence {
public int getLIS(int[] A, int n) {
int[] dp=new int[n];
int totalMax=0;
for(int i=0;i<n;i++){
int max=0;
for(int j=i-1;j>=0;j--){
if(dp[j]>max&&A[j]<A[i]){
max=dp[j];
}
}
dp[i]=1+max;
if(dp[i]>totalMax){
totalMax=dp[i];
}
}
return totalMax;
}
}
6. LCS公共最长子序列
import java.util.*;
//公共最长子序列求解
public class LCS {
public int findLCS(String A, int n, String B, int m) {
int[][] dp=new int[n][m];
//处理第0行,只要B[i]==A[0] 那么B[i+1,...m]都为1
boolean rFlag=false;
for(int j=0;j<m;j++){
if(A.charAt(0)==B.charAt(j)||rFlag==true){
dp[0][j]=1;
rFlag=true;
}
}
boolean cFlag=false;
for(int i=0;i<n;i++){
if(B.charAt(0)==A.charAt(i)||cFlag){
dp[i][0]=1;
cFlag=true;
}
}
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
if(A.charAt(i)==B.charAt(j)){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
}
}
}
return dp[n-1][m-1];
}
}
7. 背包问题
import java.util.*;
//背包问题
public class Backpack {
public int maxValue(int[] w, int[] v, int n, int cap) {
int[][] dp=new int[n][cap+1];
//处理第一个物品的价值
for(int column=0;column<=cap;column++){
if(column>=w[0]){
dp[0][column]=v[0];
}
}
for(int i=1;i<n;i++){
for(int j=1;j<=cap;j++){
int a=dp[i-1][j];
int b=0;
if((j-w[i])>=0){
b=dp[i-1][j-w[i]]+v[i];
}
dp[i][j]=Math.max(a,b);
}
}
return dp[n-1][cap];
}
}
8. 编辑字符串最小代码问题
import java.util.*;
//最优编辑问题
public class MinCost {
public int findMinCost(String A, int n, String B, int m, int c0, int c1, int c2) {
int[][] dp=new int[n+1][m+1];
//处理第一列,即删除0-i-1的字符变到空串的代价,为c1*i
for(int i=1;i<=n;i++){
dp[i][0]=c1*i;
}
//处理第一行,即增加0-j-1个字符编导B串的代价,为c0*j
for(int j=0;j<=m;j++){
dp[0][j]=c0*j;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int a=dp[i-1][j]+c1;
int b=dp[i][j-1]+c0;
int c=(A.charAt(i-1)==B.charAt(j-1)?dp[i-1][j-1]:(dp[i-1][j-1]+c2));
dp[i][j]=Math.min(Math.min(a,b),c);
}
}
return dp[n][m];
}
}
9. JAVA
* java要获取字符串中的单个字符 S.charAt(index),不能使用S[index]方式
* Math.min(a,b)只接受两个数,如果要比较三个数,可以采用Math.min(Math.min(a1,a2),a3)