【每日算法】动态规划六

1014.最佳观光组合

难度[中等]

给你一个正整数数组 values,其中 values[i] 表示第 i 个观光景点的评分,并且两个景点 i 和 j 之间的 距离 为 j - i。

一对景点(i < j)组成的观光组合的得分为 values[i] + values[j] + i - j ,也就是景点的评分之和 减去 它们两者之间的距离。

返回一对观光景点能取得的最高分。


示例 1:

输入:values = [8,1,5,2,6]
输出:11
解释:i = 0, j = 2, values[i] + values[j] + i - j = 8 + 5 + 0 - 2 = 11
示例 2:

输入:values = [1,2]
输出:2

已知:f(i,j)=values[i] + i + values[j] - j (i小于j),求f(i,j)最大
f(i,j)最大,在j之前的values[i]+i 最大,与当前的values[j]-j 最大值

定义两个数组dp_plus[j]为j之前最大值,dp[j]要求的结果

dp[j]=max(dp[j-1],dp_plus[j]+values[j]-j)
dp_plus[j]=max(dp_plus[j-1],values[j]+j)
class Solution(object):
    def maxScoreSightseeingPair(self, values):
        n=len(values)
        dp_plus=[0]*(n+1)#前j个的和的最大值
        dp=[0]*n #保存最终的结果
        dp_plus[1]=values[0]+0
        for j in range(1,n):
            dp[j]=max(dp[j-1],dp_plus[j]+values[j]-j)
            dp_plus[j+1]=max(dp_plus[j],values[j]+j)
        # print(dp_plus)
        return dp[-1]

121.买卖股票的最佳时机

难度[简单]

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

定义f(x)为第x天所能获取的最大利润,最大利润有买入时的价格,和当天价格的差值
定义买入的价格为ru,所有f(x)=max(prices[x]-ru,f(x-1))
ru的值为min(ru,prices[x])

class Solution(object):
    def maxProfit(self, prices):
        n=len(prices)
        dp=[0]*n#保存最大的利润
        dp[0]=0#第一天的利润为0
        ru=prices[0]#第一天就买入
        res=0
        for i in range(1,n):
            ru=min(prices[i],ru)#之前买入,与当前买入取最小值买入
            dp[i]=max(dp[i-1],prices[i]-ru)#第i天所能获取的最大利润
            res=max(res,dp[i])
        return res

122.买卖股票的最佳时机II

难度[中等]

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

 

示例 1:

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
示例 2:

输入: prices = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:

输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

第一种:贪心算法
贪心算法只求局部最优解,再把每个局部最优的
遇到比前一个价格高的就卖出,累计求和

def maxProfit2(self, prices):
    res=0
    #低价买入,高价卖出
    n=len(prices)
    for i in range(1,n):
        # print(res,prices[i]-prices[i-1])
        res+=max(0,prices[i]-prices[i-1])
    return res

第二种: 动态规划
因为可以频繁买入卖出,所以针对每一天的股票都有可能持有或不持有,所以定义两个状态,f(i,(0|1)),表示持有当天或不持有时获取的最大利润

不持有第i天股票时的最大利润,有两种可能:前一天不在持有,前一天持有当天卖出
f(i,0)=max(f(i-1,0),f(i-1,1)+prices[i])

持有第i天股票时的最大利润,也有两种可能:前一天持有当天继续持有,前一天不持有当天进行买入
f(i,1)=max(f(i-1,1),f(i-1,0)-prices[i])

利润最大时为最后一天时把手里的股票给卖出去dp[-1][0]

class Solution(object):
    def maxProfit(self, prices):
        n=len(prices)
        dp=[[0]*2 for _ in range(n)]
        dp[0][0]=0
        dp[0][1]=-prices[0]
        for i in range(1,n):
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
        #最大利润为最后一天不在持有
        return dp[-1][0]

309.最佳买卖股票时机含冷冻期

难度[中等]

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

f(i)为第i天的最大利润,因为可以多次买卖,所以第i天有两种状态f(i,0)持有股票时的最大利润,和f(i,1)不持有股票时的最大利润;又因为在卖出的第二天是处于冷冻期的,无法进行交易,所以还需要一个状态f(i,2)处于冷冻期时的最大利润

持有股票时的最大利润:f(i,0)
第i天持有股票,那么可以有前一天持有,或前一天不持有,当天刚买入
f(i,0)=max(f(i-1,0),f(i-1,1)-prices[i])
不持有股票时最大利润: f(i,1)
第i天不持有时,则前一天也不持有,或前一天持有并且卖出后,当天处于冷冻期也不再持有
f(i,1)=max(f(i-1,1),f(i-1,2))
处于冷冻期时的最大利润:f(i,2)
当天处于冷冻期,则前一天持有股票,并且当天卖出后,
f(i,2)=f(i-1,0)+prices[i]
posted @ 2021-09-08 15:01  Hitechr  阅读(45)  评论(0编辑  收藏  举报