(笔记自用)leetcode:买卖股票的最佳时期

题目描述:

给定一个数组 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。

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104

解法一:暴力破解遍历算法----超出时间限制(遍历两次)

int maxProfit(int* prices, int pricesSize) 
{
    //卖出价>买入价-->正数
    //计算关键是前一个数减后一个数的最大差值
    int buyin=0,buyout=1;
    int profit=0;
    int max=0;
    for(int i=0;i<pricesSize;i++)
    {
        for(int j=i+1;j<pricesSize;j++)
        {
            if((prices[j]-prices[i])>0 && (prices[j]-prices[i])>max)
                max=(prices[j]-prices[i]);
        }
    }
    return max;
}

解法二:贪心算法(遍历一次)

int maxProfit(int* prices, int pricesSize) 
{
   int minprices=0xFFFFFF;
   int maxprofit=0;
   for(int i=0;i<pricesSize;i++)
   {
        if(prices[i]<minprices)
            minprices=prices[i];
        else
        {
            maxprofit = (prices[i]-minprices) > maxprofit ? prices[i]-minprices : maxprofit;
        }
   }
   return maxprofit;

}
算法思想:

贪心算法的核心是计算历史最低买入价格和历史卖出的最高利润,遍历一次的关键就是更新每日的历史最低买入价格和历史卖出的最高利润,注意是历史的,而非当天的。

算法思路就是,对每一天的股票价格进行判断,若下于历史最低买入价格,则更新历史最低买入价格;否则,假设当天卖出(当天价格-历史最低买入价格,该步骤就自动完成了买入日在卖出日之前的前提),计算其利润,判断是否能刷新最高卖出利润。最后返回历史最高买入利润。

解法三:动态规划

int maxProfit(int* prices, int pricesSize)
{
    //动态规划,dp[i][j]在第i天是否持有股票 j = 1持有  j = 0卖出 
    int dp[pricesSize][2];
    dp[0][0] = 0;               
    dp[0][1] = -prices[0];      

    //dp[i][0]表示第i天持有股票的利润
    //dp[i][1]表示第i天不持有股票的利润

    for(int i = 1; i < pricesSize; i++ )
    {
        //第i天不持有股票,有两种情况 ①第i-1天之前就卖出了股票  ②第i-1天卖出股票
        dp[i][0] = fmax(dp[i-1][0],dp[i-1][1] + prices[i]);
        //第i天持有股票,有两种情况 ①第i-1天之前就买入股票了  ②第i-1天买入股票
        dp[i][1] = fmax(dp[i-1][1],-prices[i]);
    }
    return dp[pricesSize-1][0];
}

算法思想:

1.首先需要确定dp数组的含义。该题需要使用二维dp数组,因为对于每一天的股票价格,都有两个状态:①dp[i][0]:表示第i天不持有股票的利润        ②dp[i][1]表示第i天持有股票的利润            注意,不持有有两种可能: ①第i-1天当天卖出   ②第i-1天之前就已经卖出                                                    持有也有两种可能: ①第i-1天当天买入   ②第i-1天之前就已经买入

2.其次,需要确定规则。首先我们需要求的是利润而非所持有的金钱,因此若在第i天买入,则第i天的利润是-prices[i]。第i天的利润状态需要由第i-1天的利润状态得出,故需要从前往后进行推导,因此初始化时需要确认第一天的利润状态,即第一天买入与否。之后第二天的利润状态由第一天的利润状态推导,以此类推。如第二天持有股票的最大利润=第一天就买入股票利润 和 第二天买入股票利润  的最大值。

3.然后,需要确定第i天dp数组两个状态的数值表示,正如第一点所言,持有和不持有都有两种可能,这里的值只要取其中最大的部分就好。比如,第i天持有股票的最大利润dp[i][1]=  max(①第i1天当天买入收益(-prices[i])   或   ②第i-1天或之前就已经卖出收益dp[i-1][1] )

4.最后返回最后一天,即第pricesSize-1天不持有股票的最大利润。

心得笔记:动态规划是一种针对前后关系计算当前状态的算法,由前一个或后一个的状态得到当前状态,适用于由前后联系的题目。比如该题目就是计算每一天的利润状态,而每一天的利润状态又分两类,持有股票的利润状态和不持有股票的利润状态(故该题使用二维数组会更省时省力)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值