博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态编程(Dynamic Programming)
阅读量:6084 次
发布时间:2019-06-20

本文共 2271 字,大约阅读时间需要 7 分钟。

本文素材来自视频,请自备梯子观看:

:动态编程分为如下几步:

  1. 将复杂问题拆分成多个较简单的子问题
  2. 对每个子问题只计算一次,然后使用数据结构(数组,字典等)在内存中存储计算结果
  3. 子问题的计算结果按照一定规则进行排序(如,基于输入参数)
  4. 当需要再次运算子问题时直接使用已存储的计算结果而非再次运算以提升求解性能

这种存储计算结果以备再次使用称之为:Memoization(这个词,不知道怎么翻译好)

以斐波那契数列为例来说明:

1、使用递归实现:

def fib(n):    if n < 1:        raise ValueError('参数n必须为大于0的整数')    if n == 1 or n == 2:        return 1    return fib(n-2)+fib(n-1)

这种方法是经典的递归运算。以fib(5)为例,整个求解过程可以拆分为:

图片来自Youtube
我们可以看出,fib(2)被计算三次,fib(3)与fib(1)各被计算2次,时间复杂度为O(2^n)。

2、对递归进行改进

def fib_memory(n):    d = dict()    _fib_memory(n, d)def _fib_memory(n, temp_dict):    if n < 1:        raise ValueError('参数n必须为大于0的整数')    if type(temp_dict) is not dict        raise TypeError('参数temp_dict必须为dict类型')    if n in temp_dict:        return temp_dict[n]    if n == 1 or n == 2:        result = 1    else:        result = fib_memory(n-1, temp_dict)+fib_memory(n-2, temp_dict)    temp_dict[n] = result    return result

图片来自Youtube

优化后,时间复杂度降为O(n)。优化后的算法依然使用了递归,当参数较大时(如,1000)会导致栈溢出:
RecursionError: maximum recursion depth exceeded in comparison

3、脱离递归:

def fib_bottom_up(n):    l = [None]*(n+1)    return _fib_bottom_up(n, l)def _fib_bottom_up(n, temp_list):    if n < 1:        raise ValueError('参数n必须为大于0的整数')    if type(temp_list) is not list:        raise TypeError('参数temp_list必须为list类型')    if temp_list[n] is not None:        return temp_list[n]    if n == 1 or n == 2:        return 1    temp_list[1] = 1    temp_list[2] = 1    for i in range(3, n+1):        temp_list[i] = temp_list[i-1]+temp_list[i-2]    return temp_list[n]

图片来自Youtube

改进之后的算法不再使用递归,时间复杂度依然是O(n)。


对以上三种实现编写测试用例:

# coding=utf-8import tempimport unittestclass TestDif(unittest.TestCase):    def test_fib_0_throw_value_error(self):        with self.assertRaises(ValueError):            temp.fib(0)    def test_fib_1_return_1(self):        result = temp.fib(1)        self.assertEqual(1, result)    def test_fib_10_return_false(self):        result = temp.fib(10)        self.assertFalse(result == 10)    def test_fib_memory_10_return_false(self):        result = temp.fib_memory(10)        self.assertNotEqual(result, 10)    def test_fib_bottom_up_1000_return_true(self):        result = temp.fib_bottom_up(1000)        print(result)        self.assertTrue(result > 100000)if __name__ == "__main__":    unittest.main()

小结

无意中在Youtube上看到这段视频,就翻译整理下来与大家共享。

转载地址:http://wwuwa.baihongyu.com/

你可能感兴趣的文章
Internet Message Access Protocol --- IMAP协议
查看>>
Linux 获取文件夹下的所有文件
查看>>
对 Sea.js 进行配置(一) seajs.config
查看>>
第六周
查看>>
解释一下 P/NP/NP-Complete/NP-Hard 等问题
查看>>
javafx for android or ios ?
查看>>
微软职位内部推荐-Senior Software Engineer II-Sharepoint
查看>>
sql 字符串操作
查看>>
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>
根据Uri获取文件的绝对路径
查看>>
Flutter 插件开发:以微信SDK为例
查看>>
.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何修复处理?...
查看>>
边缘控制平面Ambassador全解读
查看>>
Windows Phone 7 利用计时器DispatcherTimer创建时钟
查看>>
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>
MapReduce的模式,算法以及用例
查看>>
《Advanced Linux Programming》读书笔记(1)
查看>>