键指offer——动态规划与贪婪算法+面试题14:剪绳子(p94

编程入门 行业动态 更新时间:2024-10-28 08:27:59

键指offer——动态规划与贪婪算法+面试题14:剪<a href=https://www.elefans.com/category/jswz/34/1739323.html style=绳子(p94"/>

键指offer——动态规划与贪婪算法+面试题14:剪绳子(p94

文章目录

    • 动态规划(dp,Dynamic Programming)
        • 动态规划求解的问题的四大特点:
        • 理解过程:背包问题
        • 练习:
        • 总结:
    • 贪婪算法(贪心算法)
        • 该算法存在的问题:
        • 贪婪算法适合用的问题:
    • 面试题14:剪绳子

动态规划(dp,Dynamic Programming)

如果编程题是求一个问题的最优解(通常是最大值或最小值),而且该 问题能够分解为若干个子问题,并且子问题之间还有重叠的更小的子问题,就可以考虑用动态规划来解决。

动态规划求解的问题的四大特点:
  1. 求一个问题的最优解;
  2. 整体问题的最优解是依赖各个子问题的最优解;
  3. 大问题可以分成若干个子问题,这些子问题之间还有相互重叠的更小的子问题;
  4. 从上往下分析问题,从下往上求解问题。

由于子问题在分解大问题的过程中重复出现,为了避免重复求解子问题,可以从下往上的顺序先计算出小问题的最优解并存储下来(一般都是存在一位数组或者二维数组里),并把子问题的最优解组合起来逐步解决大的问题。

动态规划功能强大,它能够解决子问题并使用这些答案来解决大问题。但仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用。

理解过程:背包问题

假设你是个小偷,背着一个可装4磅东西的背包。

方法就是使用动态规划,先解决子问题,再逐步解决大问题。

最初网格是空的,当网格被你填满之后,就找到了问题的答案。

其实,在计算每个单元格的价值时,使用的公式都是相同的,不论是填充值的时候还是计算最大值的时候:

练习:


方法就是之前的背包问题同样的解决方法:

总结:

 需要在给定约束条件下优化某种指标时,动态规划很有用。
 问题可分解为离散子问题时,可使用动态规划来解决。
 每种动态规划解决方案都涉及网格。
 单元格中的值通常就是你要优化的值。
 每个单元格都是一个子问题,因此你需要考虑如何将问题分解为子问题。
 没有放之四海皆准的计算动态规划解决方案的公式。

贪婪算法(贪心算法)

所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅仅是在某种意义上的局部最优解。

贪心算法没有固定的算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性(即某个状态以后的过程不会影响以前的状态,只与当前状态有关。)

所以,对所采用的贪心策略一定要仔细分析其是否满足无后效性。

该算法存在的问题:

不能保证求得的最后解是最佳的;
不能用来求最大值或最小值的问题;
只能求满足某些约束条件的可行解的范围。

贪婪算法适合用的问题:

贪心策略适用的前提是:局部最优策略能导致产生全局最优解。

实际上,贪心算法适用的情况很少。一般对一个问题分析是否适用于贪心算法,可以先选择该问题下的几个实际数据进行分析,就可以做出判断。

贪婪算法的优点——简单易行!贪婪算法很简单:每步都采取最优的做法。用专业术语说,就是你每步都选择局部最优解,最终得到的就是全局最优解。

在有些情况下,完美是优秀的敌人。有时候,你只需找到一个能够大致解决问题的算法,此时贪婪算法正好可派上用场,因为它们实现起来很容易,得到的结果又与正确结果相当接近。

面试题14:剪绳子

题目描述:
给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0] * k[1] * … * k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。

分析:

  • 首先是动态规划法来解题:将最优解存储在新建数组dp里,dp数组中的第i个元素就表示把长度为i的绳子剪成若干段之后各段长度乘积的最大值。求出每次剪绳子之后乘积的最大值,计算顺序自下而上。从绳子长度length=4开始就有了多种剪切方法:2*21*3,因此0-3为默认值lemgth[i],从length=4开始用动态规划计算最优值。

  • 接下来是贪婪算法,当length>=5时,我们尽可能多的剪长度为3的绳子,当剩下绳子长度为4时,将绳子剪成长度为2的绳子。这个思路还是蛮复杂的,比动态规划复杂一些,但解决起来又很简单。

代码:

  • 动态规划:
int maxProductAfterCutting_dp(int length)
{if(length == 0 || length ==1)return 0;if(length == 2)return 1;if(length == 3)return 2;int *dp = new int[length+1];//最终要求length的最优解dp[0] = 0;dp[1] = 1;dp[2] = 2;dp[3] = 3;int max=0;for(int i=4;i<length+1;i++){for(int j=1;j<=i/2;j++)//求出将长度为i的绳子剪成若干段的乘积最大值放到dp[i]里,最终得到长度为length的绳子长度剪成若干段的乘积最大值{int x = dp[j]*dp[i-j];if(x > max)max = x;dp[i] = max;}}max = dp[length];//resultsdelete[] length;return max;
}
  • 贪婪算法:
int maxProductAfterCutting_tanlan(int length)
{//-----------------0,1,2,3自行解决--------------------if(length == 0 || length ==1)return 0;if(length == 2)return 1;if(length == 3)return 2;//------------------仍然是长度大于等于4时开始有了多种减法------------------//尽可能多减去长度为3的绳子int timesOf3 = length/3;//判断当绳子剩下长度为4时,不能再减去长为3了,因为此时2*2的价值更大,所以3的倍数-1if(timesOf3 % 3 == 1)timesOf3 -= 1;//当剩下的值为0,2或者4时的操作,就是让其减去2int timesOf2 = (length - timesOf3*3)/2;//剩下绳子长度不可能为1,因为4里把1包括了;不可能为3因为3的倍数都会被减去return (int)(pow(3,timesOf3))*(int)(pow(2,timesOf2));//结果就是剪成长度为3或者2,所以有了这个操作}

更多推荐

键指offer——动态规划与贪婪算法+面试题14:剪绳子(p94

本文发布于:2024-02-13 03:41:39,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1690517.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:绳子   算法   贪婪   面试题   动态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!