算法学习(2):动态规划

在算法问题的求解中,比较常见的一种思想是递归。将复杂度较大的问题,转化为复杂度低的问题的集合来进行解决。逐步向下,直至问题的复杂度足够低,就能通过人工规则来实现求解。
但是今天在刷算法题目时,遇到了一个用递归解决起来非常费时间的题目。然后通过查找相关信息,就发现原来还有一种叫做动态规划的方法来求解算法问题。

动态规划是在递归的思路上,加入了对于子问题的解的备忘的方法。

在某些问题中,将一个问题分为几个子问题,然后将子问题拆解为子子问题,不断拆分,直至人工规则可解。但是如果子问题之间存在很大的重合度,那么子子问题的求解就会被重复很多次。因此,将子子问题的解记录下来,并在后期对父问题的求解中,直接使用这些记录,而不是再重新进行求解。这样不停的自底向上递归,直至求解出问题。

题目:

312. Burst Balloons Question Editorial Solution

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.

Find the maximum coins you can collect by bursting the balloons wisely.

Note:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
代码:

class Solution(object):
    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if nums==0:
            return 0

        nums=[1]+nums;
        nums.append(1)
        n=len(nums)
        dp=[[0]*n for i in range(n)] #动态规划算法,自底向上来实现
        # dp中存储从left~right的子序列的maxcoins 的值
        for k in range(2,n): # 子序列的长度从2~n-10(由于前期做了序列的扩展,                 所以其实开始输入的序列最短也会有2个长度。
            for left in range(0,n-k): # 子序列的起始位置从0开始到最大位置
                right=left+k
                ##遍历所有left与right的组合的可能性
                ##此处循环的方式十分重要,因为长度为m的序列的结果的求解需要用到长度为m-1的子序列的结果。因此应该先求出所有的长度较小的子序列的maxcoin的结果

                #对子问题进行求解,子问题的结果与子子问题有关。
                for i in range(left+1,right): 
                    dp[left][right] = max(dp[left][right],nums[left]*nums[i]*nums[right] + dp[left][i] + dp[i][right])  ##设此时去除的数的索引为i,则取出后,得到的maxcoins的值为×××,
                    ##而且由于此前所有的更短的序列的值已经经过了计算,因此可以得到较好的结果。
        return dp[0][n-1]##返回最长的序列的值

很多时候,算法的思路,比代码实现能力要重要得多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值