动态规划

动态规划在一开始学的时候就很迷糊,然后对他很恐惧,一直没敢弄明白。直到最近要用,所以认真学了一下,理解了一点点,赶紧记下来,防止将来忘掉。
在说动态规划之前,有一个题目不得不说,那就是斐波那契数列,懂得都懂,如果要找一个通式的话,那就是:f(n) = f(n - 1) + f(n - 2) ;f(1) = f(2) = 0;第一个数和第二个数是1,以后每个数是前面两个数之和。为什么说动态规划之前要说斐波那契数列呢,这时因为动态规划和斐波那切数列有一定的相似性,斐波那切数列是两个数之和,而动态规划是从两个书中选最优的那一个。
我们可以看一道题目:

a = [10,1,2,7,6,1,5], target = 8,
在a数组中能不能找到一组数,它们的和是target 8。

用动态规划解决这道题,可以这样想:a数组一共有7个数,我们只需要知道前七个数中有没有一组数之和等于8(这不废话吗,别急,为了队形)

  • 第一层:前7个数中有没有一组数之和等于8,这时有两种可能,第七个数在这一组数中,第七个数没在这一组数中。
  • 第二层:
    • 第七个数在这一组数中,现在我们需要知道前六个数中有没有一组数之和等于3(8 - 5 = 3)
    • 第七个数没在这一组数中,现在我们需要知道前六个数中有没有一组数之和等于8(8 - 0 = 8)
    • 第二层总结:现在我们就从“前七个数中有没有一组数之和等于8”,分裂出两个子问题“前六个数中有没有一组数之和等于3”和“前六个数中有没有一组数之和等于8”
  • ………………

如此往下推,虽然问题的数量变多了,但是有没有发现,如果写出通式,会和斐波那切数列的类似。
我们把前n个数中有没有一组数之和等于target设为f(n,target) ,就可以写出这样的式子:

f(n,target) = f(n - 1,target - a[n]) || f(n - 1,target)

也就是只要f(n - 1,target - a[n]) 和f(n - 1,target)只要有一个为真f(n,target)就为真。
如此一直求下去,一直求到我们一开始就知道值的位置(出口),然后回溯,便可以求出f(n,target)的值,那么出口在哪呢,这一道题一共有三个出口:

  • 首先当然是使式子成立的出口,当求着求着发现a[n]等于target的时候,就说明后面的已经满足条件了,不需要继续向前找了,这时返回真即可
  • 然后是式子不成立的出口,一种是target大了,求到第一个数,发现数组里的数全要了,和还是小于target,显然式子不成立,返回假
  • 另一种是target小了,在某一次求值的时候,如果选择数组中的这个数,会使target变成负数,要从前面找出一组数之和为负数(本题数组的数全是正数),这显然不可能,这也是个出口,式子不成立,返回假

这三个出口,实际包含了所有将式子求到最后可能的情况,有了它们,便可以解答题目。

这还没完,如果仅仅这样做,我们想一下,第二层分出两条路,第三层分出四条路,第四层的时候分出了8条路,这8条路都要计算前4个数有没有一组数等于target,这里的target可能相等(这道题效果不明显),如果相等,就会做重复的计算,大大增加时间复杂度,因此,用适当的数组标记一下,用空间复杂度换时间复杂度,例如:book[n][target] = true/false;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值