算法和数据操作-动态规划与贪婪算法
作者:互联网
动态规划是热门话题,如果一个面试题就问题的最优解,通常是最大值和最小值,而且能分解成若干个子问题,子问题也能分解更小的子问题,就能考虑动态规划
线分析要能否把大问题分解成小问题,小问题存在最优解,然后把小问题组合起来能够得到整个问题的最优解,用动态规划
为了避免重复求子问题,可以用从下往上的顺序计算子问题的最优解并存储下来,以此为基础球的最大问题的最优解,从上往下分析问题,从下往上求解问题
在用动态规划的时候,每一步都可能面临若干选择
动态规划四个特点:
1.求一个问题的最优解
2.整体问题的最优解依赖于各个子问题的最优解
3.大问题可以分解为若干个小问题,小问题之间还有更小的子问题
4.从上往下分析问题,从下往上求解问题
贪婪算法和动态规划算法不一样,应用贪婪算法的时候,每一步都可以做出一个贪婪选择,基于这个选择得到最优解
面试题14.剪绳子
题目:给你一根长度为n的绳子,请把绳子剪成n段(m,n都是整数,n>1,m>1),每段绳子的长度记为k[0],k[1],……k[m],请问k[0]*k[1]*……k[m]可能的最大成绩是多少?例如当绳子的长度未8,我们把他剪成长度为2,3,3的3段,此时得到的最大乘积为18
常规时间O(n^2),空间O(n)-》动态规划
时间空间都为O(1)的贪婪算法
动态规划方法
定义f(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值
在剪第一刀的时候,我们有n-1种可能,也就时间出来的第一段绳子的可能长度为1,2,……n-1。因此f(n)=max(f(i)*f(n-1)),其中0<i<n
这是一个从上到下的递归公式,会有重复子问题,大量不必要的计算,更好的办法是从下到上
当绳子长度为2的时候,只能剪成长度都为1的两段,因此f(2)等于1,当绳子长度为3的时候,可能把绳子剪成长度分别为1和2的两端或者长度都为1的三段,由于1*2>1*1*1,因此f(3)=2
public static int maxProductAfterCutting_solution1(int length){ if(length==1){ return 0; } else if(length==2){ return 1; } else if(length==3){ return 2; } int[] products=new int[length+1]; products[0]=0; products[1]=1; products[2]=2; products[3]=3; int max=0; for(int i=4;i<=length;i++){ max=0; for(int j=1;j<=i/2;j++){ int product=products[j]*products[i-j]; if(max<product){ max=product; } products[i]=max; } } max=products[length]; return max; }
贪婪算法
长度剩下5以上,尽可能多剪长度为3的绳子,长度为4的时候,尽量剪长度为2的绳子
public static int maxProductAfterCutting_solution2(int length){ if(length<2){ return 0; } else if(length==2){ return 1; } else if(length==3){ return 2; } int timesOf3=length/3; if(length-timesOf3*3==1){ timesOf3=timesOf3-1; } int timesOf2=(length-timesOf3*3)/2; return (int)(pow(3,timesOf3))*(int)(pow(2,timesOf2)); }
在n>=5的时候,可以证明2(n-2)>n并且3(n-3)>n,当绳子长度大于等于5,我们把他剪成长度为3或者2的绳子段。另外当n>=5时,3(n-3)>=2(n-2)因此我们尽可能减去长度为3的段
当绳子长度为4的时候,剪一刀,2*2>3*1
标签:int,绳子,length,问题,算法,贪婪,长度,最优,动态 来源: https://www.cnblogs.com/ak918xp/p/14453654.html