1.前言
第一次接触动态规划,不知道具体什么意思,做了题才发现动态规划就是把大问题变成小问题,并解决了小问题重复计算的方法称为动态规划。比如上楼梯,一次上一阶或二阶,求有多少种算法,就可以拆成最后一阶的方法数等于前一阶的方法数加前两阶的方法数,这就是递归算法。但是这样往往会超出时间限制,因为里面有大量的重复,比如一共5阶,F(5)=F(4)+F(3),其中F(4)=F(3)+F(2),这里面F(3)就被重复计算了,这时我们需要将算好的值储存下来,避免重复计算,这就是记忆递归算法。
递归是一种程序的实现方式:函数的自我调用。
动态规划:是一种解决问 题的思想,大规模问题的结果,是由小规模问 题的结果运算得来的。动态规划可用递归来实现(Memorization Search)
使用场景
满足两个条件
-
满足以下条件之一
-
求最大/最小值(Maximum/Minimum )
-
求是否可行(Yes/No )
-
求可行个数(Count(*) )
-
-
满足不能排序或者交换(Can not sort / swap )
2.实战
2.1第70题
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
心得:很经典的题目,用动态规划,之前一直有个疑问就是,递归的顺序是怎么执行的,是同时计算同一层的两个F(n-1)和F(n-2),还是先计算位于前面的F(n-1),直到算出F(n-1)再计算F(n-2),这次我直接打印出来了,发现是先递归计算出位于前面的F(n-1),这时该储存的已经储存好了,后面计算F(n-2)时就不会重复计算了。
改成自下而上dp(动态规划)
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n==1:
return 1
elif n==2:
return 2
dp = [0]*(n+1)
dp[1] = 1
dp[2] = 2
for i in range(3,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
因为该问题符合斐波那契数列,直接算
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
a = b = 1
for i in range(2, n + 1):
a, b = b, a + b
return b
2.2第118题
给定一个非负整数 numRows
,生成「杨辉三角」的前 numRows
行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
class Solution(object):
def generate(self, numRows):
"""
:type numRows: int
:rtype: List[List[int]]
"""
if numRows==1:
return [[1]]
result = [[1]]
for i in range(2,numRows+1):
current = [1]*i
if i>2:
for j in range(1,i-1):
current[j] = result[i-2][j-1]+result[i-2][j]
result.append(current)
return result