python动态规划

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法百度百科。

动态规划要点:最优子结构,边界,状态转移函数。

最优子结构:在每个阶段最优状态可以从之前某个阶段的状态直接得到

边界:最小子集的解

状态转移函数:从一个阶段向另一个阶段过渡的具体形式,描述两个相邻子问题之间关系

几个简单例子:

假设你正在爬楼梯,需要n阶才能到达楼顶

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

如:

示例1:

输入: 2

输出: 2

解释: 有两种方法可以爬到楼顶。

1. 1 阶 + 1 阶

2. 2 阶

示例2:

输入: 3

输出: 3

解释: 有三种方法可以爬到楼顶。

1. 1 阶 + 1 阶 + 1 阶

2. 1 阶 + 2 阶

3. 2 阶 + 1 阶

解析:

如果给的两个示例看的不是特别清楚,你可以当阶梯为0,那么上楼梯方法0种这是必然,当阶梯只有1那么上楼梯方法只有1种:

当4个台阶:

输入:4

输出:4

1. 1阶 + 1阶 + 1阶 + 1阶

2. 2阶 + 2阶

3. 1阶 + 2阶 + 1阶

4. 2阶 + 1阶 + 1阶

5. 1阶 + 1阶 + 2阶

那么得到:

阶梯数爬楼梯方法

00

11

22

33

45

...

如果感觉看的不明显可以推理一下5阶,6阶...

可以得到当我们想爬n阶楼梯,我们可以得到: p(n-1) + p(n-2)p为爬楼梯方法

代码

class Solution:
def climbStairs(self, n: int) -> int:
num_list = [0,1,2]
if n==1:
return num_list[1]
elif n==2:
return num_list[2]
else:
for i in range(3,n+1):
num_list.append(num_list[i-1]+num_list[i-2])
print(num_list)
return num_list[n]
obj = Solution()
result = obj.climbStairs(10)
print(result)
提交LeetCode只击败了12.72%的人。通过优化
class Solution:
def climbStairs(self, n: int) -> int:
a,b,c = 0,1,2
if n == 1:
return b
if n == 2:
return c
while n>0:
c = a + b
a,b = b,c
n -= 1
return c
obj = Solution()
result = obj.climbStairs(8)

2.最子序列求和LeetCode

53. 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],

输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

解析:

对于上述序列:

nums = [-2,1,-3,4,-1,2,1,-5,4],当i从0~len(nums).其对应子序列和可以得到:

dp = [-2, 1, -2, 4, 3, 5, 6, 1, 5] # dp[i]代表从0~i区间,所包含i元素的连续子数组,最大之和。

代码:

class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 判断边界
if len(nums) == 0:
return 0
# 定义一个表格进行存储上一个子问题的最优解
d = []
d.append(nums[0]) # 第一个最优解为第一个元素
max_ = nums[0] # 返回的最大值
for i in range(1, len(nums)):
if nums[i] > nums[i] + d[i - 1]:
d.append(nums[i])
else:
d.append(nums[i] + d[i - 1])
if max_ < d[i]:
max_ = d[i]
print(d)
obj = Solution()
result = obj.maxSubArray([-2,1,-3,4,-1,2,1,-5,4])
print(result)

3.买卖股票的最佳时机;ettCode

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]

输出: 5

解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。

注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]

输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

解析:

定义一个变量记录买入最小金额。定义一个数组存放每天最大利润。若当天利润大于前一天利润加入数组中,若当天利润小于前一天利润,则让当天利润等于前一天利润,并加入数组中。

代码:

class Solution:
def maxProfit(self, prices: List[int]) -> int:
if len(prices) <= 1:
return 0
profit = [0,]
# 买入最低价格
min_v = prices[0]
for i in range(1,len(prices)):
max_profit = max(profit[i-1],prices[i]-min_v)
profit.append(max_profit)
if prices[i] < min_v:
min_v = prices[i]
return profit[-1]
obj = Solution()
res = obj.maxProfit([7,1,5,3,6,4])
print(res)