leetcode63 股票的最大利润及其变体(待完善)

题目1:买卖股票的最佳时机 I

来源:leetcode63 股票的最大利润 和 LC121. 买卖股票的最佳时机

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

标签一次买卖

分析:动态规划

         状态: dp[i]代表第i天能获得的最大利润                       

         状态转移方程: dp[i] =max(不做任何操作即前i-1天的最大值, 第i天卖出股票的最大值)   =max(dp[i-1],prices[i] - minval)

         改进: 为了节省空间,可以将维护d[]改为维护最大利润 profit

复杂度:       时间复杂度:O(n)                        空间复杂度:O(1)

代码:

# LC63  LC121
def maxprofitOneSale(prices):
    minval, profit = int(1e9), 0
    for i in range(len(prices)):
        minval = min(prices[i], minval)
        profit = max(profit, prices[i] - minval)
    return profit

题目2:买卖股票的最佳时机 II

来源:LC 122. 买卖股票 的最佳时机 II 和 百度面试

 描述:给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

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

标签多次买卖

分析:

    贪心:只要能获利 就进行买卖
        如果 prices[i]>prices[i-1],就将该差值加入表示邻近的两天有股票的买卖

        复杂度:         时间复杂度:O(n)         空间复杂度:O(1) 
    动态规划
        状态
            d[i][0]:代表第i天交易完成后,手中不持股票时的最大利润 (不持股票包括第i-1天没有股票 以及 第i-1天有股票并在第i天将股票卖掉)
            d[i][1]:代表第i天交易完成后,手中持有股票时的最大利润(持有股票包括第i-1天有股票 以及 第i-1天没有股票并在第i天买到了新股票)
        状态方程
            d[i][0]=max(d[i-1][0],d[i-1][1]+prices[i])
            d[i][1]=max(d[i-1][0],d[i-1][0]-prices[i])
        初始状态:
            d[0][0] 第0天(对应prices的第一天 下标为0)交易结束时,没有持有股票,即没有买股票 为0.
            d[0][1] 第0天(对应prices的第一天 下标为0)交易结束时,持有股票,即买了第一个股票,为-prices[0]
        改进: 为减少时间复杂度,可以用变量sale 代表d[·][0],用变量buy代表d[·][1]  
        返回:最终返回 sale (手中不含股票)
        复杂度:         时间复杂度:O(n)         空间复杂度:O(1) 

代码:

# 贪心
def maxprofitManySale1(prices):
    profit = 0
    for i in range(1, len(prices)):
        if prices[i]>prices[i-1]:
            profit += prices[i]-prices[i-1]
    return profit
# 动态规划
def maxprofitManySale2(prices):
    sale, buy = 0, -prices[0]
    for i in range(1, len(prices)):
        sale, buy = max(sale, buy+prices[i]), max(buy, sale-prices[i])
    return sale

题目3:买卖股票的最佳时机 III(多次买卖股票含手续费)

来源:714. 买卖股票的最佳时机含手续费 和 虾皮笔试

描述:给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用。你可以无限次地完成交易,但是你每次交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。返回获得利润的最大值。

        输入:prices = [1, 3, 2, 8, 4, 9], fee = 2    输出:8

标签多次买卖含手续费
分析:动态规划

        同题目2的动态规划的解法,当含手续费时 在买入股票时候多减手续费即可。

        状态:

            d[i][0]:代表第i天交易完手里没有股票的最大收益  (第i天不持有股票包括:第i-1天就不持有股票  和  第i天将股票卖掉(第i-1天持有股票) )
            d[i][1]:代表第i天交易完手里有股票的最大收益(第i天持有股票包括:第i-1天就持有股票 和 第i天买股票(第i-1天不持有股票))

        动态方程:

            d[i][0]=max(d[i-1][0], d[i-1][1]+prices[i])
            d[i][1]=max(d[i-1][1], d[i-1][0]-prices[i]-fee)

           改进:为节省空间开销,可以用 sell代替d[~][0]   buy代替d[~][1] 最后返回 sell

复杂度:   时间复杂度:O(n)         空间复杂度:O(1) 

代码:

def maxprofitManySaleWithFee(prices, fee):
    sale, buy = 0, -prices[0]-fee
    for i in range(1, len(prices)):
        sale, buy = max(sale, buy + prices[i]), max(buy, sale-prices[i]-fee)
    return sale

题目4:多次买卖股票含冷冻期

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

题目多次买卖股票含冷冻期
    给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):    你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。    卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

     输入: [1,2,3,0,2]  输出: 3    解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
分析
     状态
         d[i][0]:第i天交易结束后, 不持有股票的最大利润   
                (①第i天本身就没股票,即第i-1天结束后,不持有股票 d[i-1][0]

                  ② 第i天有股票,即第i-1天结束后有股票,但是卖掉了 d[i-1][1]+prices[i]
                  ③处于冷冻期,即第i-1天卖掉了股票,导致没有股票且冷冻 d[i-1][0] )
                  d[i][0] = max(d[i-1][0],d[i-1][1]+prices[i])
         d[i][1]:第i天交易结束后,持有股票的最大利润 
                (① 第i天没买票,第i-1天就有股票 d[i-1][1]  
                  ② 第i天买的股票,此时第i-1天一定不能卖票,即d[i-1][0] = d[i-2][0],此时我们取值为 d[i-2][0]-prices[i])
                  d[i][1] = max(d[i-1][1],d[i-2][0]-prices[i])                
     状态转移方程
         d[i][0] = max(d[i-1][0],d[i-1][1]+prices[i])
         d[i][1] = max(d[i-1][1],d[i-2][0]-prices[i])
    初始状态
        需要初始化两天的状态(i=0  i=1)
        d[0][0]:第0天(对应prices[0])结束后,不持有股票的最大利润   = 0
        d[0][1]:第0天(对应prices[0])结束后,持有股票的最大利润   = -prices[0]
        d[1][0]:第1天(对应prices[1])结束后,不持有股票的最大利润   = max(d[0][0], d[0][1]+prices[1])
        d[1][1]:第1天(对应prices[1])结束后,持有股票的最大利润=max(d[0][1], -prices[1]) # 第1天没买票 或 第1天买票,第0天没买
    改进
         salepre, sale, buy代替上述遍历。
复杂度:时间复杂度 O(n)   空间复杂度 O(1)

代码:

def maxprofitManySaleWithFreeze(prices):
    # 当天数小于1时
    n = len(prices)
    if n <= 1:
        return 0
    # 初始化两天的
    salepre, buy = 0, -prices[0]
    sale, buy = max(salepre, buy + prices[1]), max(buy, -prices[1])
    # 节省空间进行遍历
    for i in range(2, len(prices)):
        sale, buy, salepre = max(sale, buy + prices[i]), max(buy, salepre - prices[i]), sale
    return sale
print(maxprofitManySaleWithFreeze([4,2,7,1,11]))

题目5:两次买卖一只股票

  123. 买卖股票的最佳时机 III 

描述:一只股票的价格在4天的波动分别是  [1, 3, 1, 4]   求买卖该股票二次的最大收益(不可以同时买入同时卖出两只股 即 可以完成一次买卖后进行下一次买卖)

分析:动态规划+分治法
        本题和一次买卖股票是同一个题型  只不过本题是买卖两次且两次买卖没有关系
        可以考虑使用分治法  即  总共的最大利润 = 第一次买卖股票的获利 + 第二次买卖股票的获利
        可以设置dp[i]中i来表示一个节点  即两次买卖的分界点  如 dp[1]代表  [1,3]第1-2天的获利 + [3,1,4] 2-3天的获利 
ps:思考好分界点 以及边界

复杂度:              时间复杂度:O(n^2)                        空间复杂度:O(1)   dp可以使用原来的nums的空间

'''
股票的最大利润(2)
    题目简介:一只股票的价格在4天的波动分别是  [1, 3, 1, 4]   求买卖该股票二次的最大收益(不可以同时买入同时卖出两只股 即 可以完成一次买卖后进行下一次买卖)
    结果: 买卖两次  可以在第一天买 第二天卖   第三天卖 第四天卖
    分析:
        本题和上一题是同一个题型  只不过本题是买卖两次且两次买卖没有关系
        所以可以考虑使用分治法  即  总共的最大利润 = 第一次买卖股票的获利 + 第二次买卖股票的获利
        所以可以设置dp[i]中i来表示一个节点  即两次买卖的分界点  如 dp[1]代表  [1,3]第1-2天的获利 + [3,1,4] 2-3天的获利 
        ps:思考好分界点 以及边界
    复杂度:
        时间复杂度:O(n^2)
        空间复杂度:O(1)   
'''
def maxProfit2(nums):
    maxpro = 0
    for i in range(len(nums)):
        maxpro = max(maxpro, maxProfit1(nums[:i]) + maxProfit1(nums[i:]))
    return maxpro

题目6:两次买卖一只股票

   188. 买卖股票的最佳时机 IV

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值