剑指 Offer 63. 股票的最大利润

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

示例 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。

方法:动态规划

状态定义: d p [ i ] dp[i] dp[i]为截止到第i天所获得的最大利润

状态转移:

  • m i n n minn minn存放截止到第 i i i天时,最小的股票价格。

在这里插入图片描述

此时会有三种情况:

  1. i i i天的价格小于等于前 i − 1 i-1 i1天的最小价格,此时前 i i i天的最小价格为 p r i c e s [ i ] prices[i] prices[i],此时最大利润会变吗,现在是最低价肯定不能卖啊,所以利润还是之前的利润, d p [ i ] = d p [ i − 1 ] dp[i] = dp[i-1] dp[i]=dp[i1]
  2. i i i天的价格大于前 i − 1 i-1 i1天的最小价格,这时候就要比较一下如果今天卖出的利润了,如果 p r i c e s [ i ] − m i n n > d p [ i − 1 ] prices[i]-minn > dp[i-1] prices[i]minn>dp[i1],那证明今天卖的利润是有史以来最大,必须果断卖,就有 d p [ i ] = p r i c e s [ i ] − m i n n dp[i] = prices[i]-minn dp[i]=prices[i]minn
  3. i i i天的价格仍大于前 i − 1 i-1 i1天的最小价格,但此时 p r i c e s [ i ] − m i n n < = d p [ i − 1 ] prices[i]-minn <= dp[i-1] prices[i]minn<=dp[i1],证明今天卖的话没有以前合适,那利润仍不变, d p [ i ] = d p [ i − 1 ] dp[i] = dp[i-1] dp[i]=dp[i1]

以上就是状态转移的三种情况

初始状态: d p [ 0 ] = 0 , d p [ 1 ] = m a x ( p r i c e s [ 1 ] − p r i c e s [ 0 ] , 0 ) dp[0] = 0,dp[1] = max(prices[1]-prices[0], 0) dp[0]=0dp[1]=max(prices[1]prices[0],0);初始状态时 m i n n = m i n ( p r i c e s [ 0 ] , p r i c e s [ 1 ] ) minn = min(prices[0],prices[1]) minn=min(prices[0],prices[1])
返回值: d p [ ] dp[] dp[]中最后一项

python

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        l = len(prices)
        if l == 0 or l == 1: return 0
        dp = [0]*l
        minn = min(prices[0],prices[1])
        dp[1] = max(prices[1]-prices[0],0)
        for i in range(2,l):
            if prices[i]<=minn: # 此时只是把最小值换了,此时还不能卖呢,利润仍不变
                dp[i] = dp[i-1]
                minn = prices[i]
            elif (prices[i]-minn)> dp[i-1]: 
                dp[i] = (prices[i]-minn)
            else:
                dp[i] = dp[i-1]
        return dp[-1]

C++

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int l = prices.size();
        if(l == 0 ||l == 1) return 0;
        int dp[l];
        int minn = min(prices[0], prices[1]);
        dp[1] = max(prices[1]-prices[0], 0);
        for(int i=2; i<l; i++){
            if (prices[i]<=minn){
                dp[i] = dp[i-1];
                minn = prices[i];
            }
            else if((prices[i]-minn)> dp[i-1]) dp[i] = prices[i]-minn;
            else dp[i] = dp[i-1];
        }
    return dp[l-1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值