递归、记忆化搜索、动态规划之间的联系

在这里插入图片描述
相信很多童鞋在上学的时候虽然学习过动态规划,但是实际上对动态规划还是模糊的,其实,动态规划本质依然是递归算法,只不过是满足特定条件的递归算法。下面以LintCode343题为例,详细分析,如何使用动态规划一步一步求解,帮助大家了解动态规划的概念:

整数拆分
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

示例:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1

分析:
首先我们先看假如对4进行分割的问题,那么可以分割成 1+3、2+2、3+1的问题,然后去最大的那个分割
在这里插入图片描述同理对,下层的3和2进行分割:
在这里插入图片描述我们可以看到蓝色底纹的就是重叠子问题,更一般的,可以分割为1+n-1、2+n-2、3+n-3、、、、n-1+ 1
在这里插入图片描述
可以看出存在大量的重叠子问题,这就意味着我们可以使用记忆化搜索。
下面我们进行编码具体解决:

class Solution(object):
    def breakInteger(self,n,memo):
        '''
        记忆搜索处理最大分割  lintcode343
        :return:
        '''
        if n == 1:
            return  1
        res = -1
        for i in range(1,n):
            res = max(res,i*(n-i),i * self.breakInteger(n-i,memo))
        return  res
    def integerBreak(self, n):
        return self.breakInteger(n,memo)

上述的代码就一个递归过程,我们说了存在大量重复子问题的计算,所以为了减少计算机的重复计算。我们采用记忆化搜索,就是采用一个list存储每次的最优分割,具体如下:

class Solution(object):
	def breakInteger(self,n,memo):
        '''
        记忆搜索处理最大分割  lintcode343
        :return:
        '''
        if n == 1:
            return  1
        if memo[n] != -1:
            return memo[n]
        res = -1
        for i in range(1,n):
            res = max(res,max(i*(n-i),i * self.breakInteger(n-i,memo)))
        memo[n] = res
        return  res

    def integerBreak(self, n):
        memo = [-1 for _ in range(n + 1)]
        return self.breakInteger(n,memo)

上述就是,记忆化搜索的过程。一般的,能使用记忆化搜索的,我们也可能使用动态规划来接,记忆化搜索是自顶向下的,二动态规划是自底向上的,代码如下:

class Solution(object):
    def dp_integerBreak(self, n):
        '''
        动态规划解最大分割  lintcode343
        :param n: 
        :return: 
        '''
        memo = [-1 for _ in range(n + 1)]
        memo[1] = 1
        for i in range(2,n+1):
            for j in range(1,i):
                memo[i] = max(memo[i],j*(i-j),j+memo[i-j])
        return memo[n]

LeetCode上还有类似的题,279、 62、 63、198可以自己去练习练习
198题分析:
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值