优美的递归,华丽的动规。
优美的递归,华丽的动规。
-
递归:实质是自顶向下。
-
DP: 实质是自低向上,依次填表,以空间换时间。
- 一维DP 斐波那契 递归重叠 子元素问题。
- 二维DP就是填表。
-
选还是不选?问题
-
第一题 题目描述:选出不重叠的最长线段和。

解题思路:
-
就是找到最后一个线段:考虑他的状态
-
选还是不选?
-
选择:OPT(8)=等于它本身的值 + 他前面可选最后一个的最优解
-
不选:OPT(8)= OPT(7)
-
所以需要 3个值来记录
- i : 当前下标
- pre(i):用于记录前面最后一个可选的最优解.
- opt(i) : 用于记录当前下标最优解.
-
状态转移:如果opt(i)= A(选择)>B(不选择)?A:B
-
初始化:OPT(0) = arr[0] ; Pre[0] = 0;
递归:
public int theLongRC(int[][] qujian,int n,int[] pre){ if(n==-1){ return 0; } if(n==0){ return qujian[0][1]-qujian[0][0]; } int A = qujian[n][1]-qujian[n][0] + theLongRC(qujian,pre[n],pre); //选 int B = theLongRC(qujian,n-1,pre); //不选 return A>B?A:B; } }DP:
public int theLongDp(int[][] qujian,int n,int[] pre){ int dp[] = new int[qujian.length]; dp[0] = qujian[0][1]-qujian[0][0]; dp[1] = dp[0]; for(int i =2;i<n;i++){ int A = qujian[i][1]-qujian[i][0] + (pre[i]>=0?dp[pre[i]]:0);//选 int B = dp[i-1];//不选; dp[i] = A>B?A:B; } return dp[n-1]; }
-
-
-
第二题:选出不相邻的数字组成的最大值:4,1,1,9,3 最大为13
解题思路:
-
选还是不选?
- 选 : opt[i] = opt[i-2] + arr[i];
- 不选:opt[i] = opt[i-1];
-
状态转移:
如果opt(i)= A(选择)>B(不选择)?A:B
-
初始化:
opt[0] = 4 opt[1] = 4
递归:
public int RECtest(int[] arr,int i) { int max =0; if(i<0){ return max; }else{ int A = arr[i] + RECtest(arr,i-2); int B = RECtest(arr,i-1); return A>B?A:B; } }DP:
public int DPtest(int[] arr) { //不相邻的最大值 int[] dp = new int[arr.length]; int[] pre = new int[arr.length]; pre[0] = 0; dp[0] = arr[0]; for(int i=1;i<arr.length;i++){ int A = arr[i] + pre[i-1]; //选 int B = dp[i-1]; if(A>B){ dp[i] = A; }else{ dp[i] = B; } pre[i] = dp[i-1]; } return dp[arr.length-1]; }
-
-
第三题:给一个数列 如果 有数字相加等于k 则返回True (二位填表)

解题思路: 往前面找,直到找到刚好为K的数。
-
选还是不选?
-
选:
-
不选:
-
状态转移?
-
初始化
- subset(arr[5],9);
-
出口:
- if(s==0) return true;
- if(i0) return arr[0]s;
- 剪枝操作:如果此 arr[i] > s 那直接跳过选择的阶段,直接不选。

-
递归
public boolean RECtest2(int arr[],int k,int i){ //递归,选出数字之和等于x,如果有,返回true。 if(i<0){ return false; }else if(arr[i]==k){ return true; }else if(arr[i]>k){// 剪枝 直接不选 。 return RECtest2(arr,k,i-1); }else{ return RECtest2(arr,k-arr[i],i-1)|| RECtest2(arr,k,i-1); } } -
DP
public boolean DPtest2(int arr[],int k){ //非递归,选出数字之和等于x,如果有,返回true。 boolean dp[][] = new boolean[arr.length][k+1]; //注意看表 for(int i=0;i<arr.length;i++){ //初始化。 dp[i][0] = (arr[i] ==k); dp[0][i] = true; } for(int i =1;i<arr.length;i++){ for(int j=1;j<k+1;j++){ if(arr[i]>j){ dp[i][j] = dp[i-1][j]; }else{ dp[i][j] = dp[i-1][j-arr[i]] || dp[i-1][j]; } } } return dp[arr.length-1][k]; }
-
-

浙公网安备 33010602011771号