【温故知新】`121. 买卖股票的最佳时机` 动态规划、双指针实现

638 阅读3分钟

题目描述

给定一个数组 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 通过次数539,263提交次数940,8

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/be… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路1:双指针实现;

题目解析:给定prices数组且最大利益由买入卖出的价格决定:双指针实现/动态规划实现

  • 假设pre为买入日期;cur为卖出日期;
  • 定义当前最大利润max;
  • 遍历prices数组;
    • 如果当天价格小于买入价格,则将当天价格作为买入价格;即:if(prices[i]<prices[pre]);
      • 更新当天为最新的买入日期:pre=i;
    • 否则,得出如果当天卖出时的利润profit;即:profit=prices[i]-prices[pre];
      • 如果当天最大利润大于当前最大利润:profit>max,则更新当前最大利润,并更新最新卖出日期cur;

时空复杂度

  • 时间复杂度O(N)
  • 空间复杂度O(1)

代码

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {  
    //  数组且最大利益由买入卖出的价格决定: 
    //pre表示当前买入日期,cur表示卖出日期;max表示买入卖出获得的最大利润;

    let pre=0;cur=0;max=0;
    for(let i=1;i<prices.length;i++){
        if(prices[i]<prices[pre]){
            pre=i; //更新买入日期;
        }else{
            // 计算出当前卖出的利润;
           let profit =prices[i]-prices[pre]
           if(profit>max){
               cur=i; //更新卖出日期;
               max=profit; // 更新最大利润;
           }
        } 
    }// end of for loop
    return max
};

思路2:动态规划

第i天的最大收益,只需要知道前i天的最低点就可以得知, 前i天的最低点可以由前i-1天的最低点推算得知;

  • 动态规划三部曲
    • 定义dp含义:dp[i]表示截止第i天为止,价格最低点是多少;
    • 定义dp递推公式;
      • 前i天的最低点可由前i-1天的最低点推算可知;
      • dp[i]=Math.min(dp[i-1],prices[i])
    • 初始化dp:
      • 定义dp[0]=prices[0];含义为第0天前的最低点为prices[0] ;

时空复杂度

  • 时间复杂度O(N)
  • 空间复杂度O(N)

代码

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
   // 动态规划实现;
   // 思路:第i天的最大收益,只需要知道前i天的最低点就可以得知;
   // 前i天的最低点可以由前i+1天的最低点推算得知;
   // 定义dp含义:dp[i] 表示截止到i价格最低点多少;

   // 由此得到动态规划:dp[i]=Math.min(dp[i-1],)
   let len=prices.length;
   let max=0;
   let dp= new Array(len).fill(0)
   dp[0]=prices[0];
   for(let i=1;i<len;i++){
       dp[i]=Math.min(dp[i-1],prices[i])
       max=Math.max(prices[i]-dp[i],max)
   }// end of for loop
    return max;
};

往期动态规划回顾

完全背包🎒问题

【温故知新】322. 零钱兑换 动画演示-完全背包问题最小解-动态规划实现

【温故知新】518. 零钱兑换 II 完全背包问题组合解-动态规划实现

【温故知新】377. 组合总和 Ⅳ 完全背包问题排列解-动态规划实现

【温故知新】70. 爬楼梯进阶版 完全背包🎒问题AC-动态规划实现

01背包🎒问题

【温故知新】474. 一和零 01背包🎒问题最大解-动态规划实现

【温故知新】494. 目标和 表达式转化为01背包🎒问题-动态规划实现

【温故知新】1049. 最后一块石头的重量 II 最小重量转化为01背包🎒问题最大解-动态规划实现

【温故知新】416. 分割等和子集01背包🎒问题存在解-动态规划实现