動態規划問題
三要素:
最優子結構:子問題的最優解能夠決定這個問題的最優解
邊界:問題最小子集的解(初始范圍)
狀態轉移函數:遞推式
1爬樓梯
分析:
假定n=10,首先考慮最后一步的情況,要么從第九級台階再走一級到第十級,要么從第八級台階走兩級到第十級,因而,要想到達第十級台階,最后一步一定是從第八級或者第九級台階開始.也就是說已知從地面到第八級台階一共有X種走法,從地面到第九級台階一共有Y種走法,那么從地面到第十級台階一共有X+Y種走法.
即F(10)=F(9)+F(8)
分析到這里,動態規划的三要素出來了.
邊界:F(1)=1,F(2)=2
最優子結構:F(10)的最優子結構即F(9)和F(8)
狀態轉移函數:F(n)=F(n-1)+F(n-2)
class Solution(object):
def climbStairs(self, n):
if n <= 2:
return n
a = 1
b = 2
for i in range(3, n+1):
a, b = b, a+b
return b
2 最大子序和
給定一個整數數組nums, 找到一個具有最大和的連續子數組,返回其最大和。
分析:
最優子序列:當前值的最大子序和是(之前最大子序和+當前值,當前值)
邊界:第一個值的最大子序和是它自身
狀態轉移函數:dp[i]=max(nums[i], nums[i]+dp[i-1])
nums = [-2,1,-3,4,-1,2,1,-5,4]
dp = [-2, 1, -2, 4, 3, 5, 6, 1, 5]
class Solution(object):
def maxSubArray(self, nums):
if len(nums)==0:
return 0
# 定義一個表格用於存儲上一個問題的最優解
d = []
d.append(nums[0])
max_num = 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_num < d[i]:
max_num = d[i]
# return max(d)
return max_num
打家劫舍
最優子結構:最后一家偷不偷,偷則加上前兩位的最大值,不偷則是前一位的最大值
邊界:d[0]=nums[0], d[1]=max(nums[0], nums[1])
狀態轉移函數:d[i]=max(d[i-1], d[i-2]+nums[i])
class Solution(object):
def rob(self, nums):
if len(nums)==0:
return 0
if len(nums)<=2:
return max(nums)
dp = []
dp.append(nums[0])
dp.append(max(nums[0], nums[1]))
for i in range(2, len(nums)):
dp.append(max(dp[i-1], dp[i-2]+nums[i]))
return dp[-1]
買股票的最佳時機
[7,1,5,3,6,4]
最優子結構:f(1)的最優子結構是f(7)
邊界:f(0)=0
遞推式:f(1) = max(f(7), 4-最小金額)
其中最小金額是在變化的
class Solution(object):
def maxProfit(self, prices):
if len(prices)<=1:
return 0
dp = []
dp.append(0)
min_value=prices[0]
for i in range(1, len(prices)):
dp.append(max(dp[i-1], prices[i]-min_value))
if prices[i]<min_value:
min_value=prices[i]
return dp[-1]
使用最小話費爬樓梯
最優子結構:f(9)和f(8)
邊界:f(0)=1, f(1)=100
遞推式:f(10)=min(f(9)+cost(9), f(8)+cost(8))
class Solution(object):
def minCostClimbingStairs(self, cost):
if len(cost) <= 1:
return min(cost)
dp = []
dp.append(cost[0])
dp.append(cost[1])
for i in range(2, len(cost)+1):
if i==len(cost):
dp.append(min(dp[i-1], dp[i-2]))
else:
dp.append(min(dp[i-1]+cost[i], dp[i-2]+cost[i]))
return dp[-1]