动态规划解题方式
- 动态规划的解题方式通常分为两种:
通过定义递归方程解决,这是一种自顶向下的求解方式,通常这种方式会有很多重复计算过程,因此可以通过建立备忘录记录中间过程来进行优化;
通过定义DP(Dynamic Programming)数组来求解,这是一种自底向上的求解方式。
下面以常见的斐波拉契数列为例来说明一下上述两种求解方式。斐波那契数列(Fibonacci sequence)是指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……。即后一个数为前两个数之和。在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)# 暴力递归def fib(n):if n <= 2:return 1return fib(n-1) + fib(n-2)# 斐波那契数列def fib(n):def helper(n):if n <= 2:return 1# 如果n的值已经计算过了,则直接返回值memo[n]if n in memo:return memo[n]memo[n] = fib(n - 1) + fib(n - 2)return memo[n]# 记录已经计算的值,防止重复计算memo = {}return helper(n)print(fib(6))
leetcode题目:爬楼梯
每次最多只能爬1阶或者2阶,求爬到n阶有多少种方法?
题解:爬到n阶只需要知道第n-1阶和第n-2阶有多少种办法,所以只需要记录n-1阶 和 n-2阶的办法数即可
class Solution:def climbStairs(self, n: int) -> int:# 当 楼梯只有1阶或者2阶if n <= 2:return na = 1 # 初始化1阶楼梯有一种办法b = 2 # 初始化2阶楼梯有2种办法for i in range(3, n+1):# 空间压缩,只记录n-1阶 和 n-2阶的办法数a, b = b, a+breturn b# 时间复杂度O(n),空间复杂度O(1)
leetcode题目:买股票的最佳时间
求卖出股票的最大利益是多少?
题解:卖出减去买入,利益要求最大化,且卖出必须是在买入之后
# 暴力法class Solution:def maxProfit(self, prices: List[int]) -> int:ans = 0 # 初始化交易后股票的利益为0# 遍历可能买入的时间for i in range(len(prices)):# 遍历可能卖出的时间,看哪个时间卖出的利润最大for j in range(i + 1, len(prices)):# 卖出价格减去买入价格的利润,如果利润为负,则取0,===没有交易ans = max(ans, prices[j] - prices[i])# 交易后的利润return ans# 空间复杂度O(1),时间复杂度O(n*n)
class Solution:def maxProfit(self, prices: List[int]) -> int:minprice = float('inf') # 初始化设置最小买入价格为正无穷大maxprofit = 0 # 设置初始化最大利润为0for price in prices:# 遍历记录历史的最低价格minprice = min(minprice, price)# 判断当前卖出的最大利润,获取遍历完的最大利润maxprofit = max(maxprofit, price - minprice)return maxprofit# 空间复杂度O(1),时间复杂度O(n)
class Solution:def maxProfit(self, prices:List[int]) ->int:minprice = prices[0] # 初始化最小价格maxprofit = 0 # 初始化最大利润for price in prices:# 如果当前价格小于最低价,则替换当前价格为最低价if price < minprice:minprice = price# 如果当前利润小于当前价格减去“当前认为的最低价”,则当前利润才是最大利润if maxprofit < price - minprice:maxprofit = price - minpricereturn maxprofit# 空间复杂度O(1),时间复杂度O(n)
