【动态规划】- js 求解买卖股票问题

本文介绍了一种计算股票买卖最大利润的算法,包括直接遍历和动态规划两种方法。通过实例展示了如何找到最佳买卖时机以获得最大收益。

121. 买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。

示例 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. 直接遍历

我们需要对股票进行一次买入、一次卖出,卖出在买入之后,并且要计算最大的利润。

这里初始化一个最小值min,和一个最大的结果值max。遍历数组,如果当前数组元素小于最小值民,就更新最小值,始终让其保持最小。如果当前值减去最小值大于最大值,就更新最大值。直到遍历完数组所有的元素,返回最后的结果。

2. 动态规划

对于这道题,我们可以使用动态规划来解决。这里我们只需要进行一次买入卖出。那到最后交易时,可能会有三种状态:

  • dp[0]:一直没有买
  • dp[1]::到最后只买了一笔,未卖出
  • dp[2]::到最后只卖了一笔,并卖出

由于第一种状态未进行任何操作,所以可以不用记录。然后我们对后两种状态进行转移:

  • dp[1] = Math.max(dp[1], -prices[i]):前一天也是b1状态或者是没有任何操作,今天买入一笔变成b1状态;
  • dp[2] = Math.max(dp[2], dp[1] + prices[i]):前一天也是s1状态或者是b1状态,今天卖出一笔变成s1状态;

(1)直接遍历

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
    let max = 0
    let min = prices[0]

    prices.forEach( item => {
        if(item < min) min = item
        if(item - min > max) max = item - min
    })
    return max
};

复杂度分析:

  • 时间复杂度: O(n),其中n是数组的长度,我们需要将数组遍历一遍
  • 空间复杂度: O(1),这里只需要常数空间来储存最小值min和最大结果值max

(2)动态规划

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
    let len = prices.length;
    const dp = [0, -prices[0], 0]
    
    for (let i = 1; i < len; i++) {
        dp[1] = Math.max(dp[1], -prices[i])
        dp[2] = Math.max(dp[2], dp[1] + prices[i])
    }
    return dp[2];
}

复杂度分析:

  • 时间复杂度:O(n),其中 n 是数组 prices 的长度。
  • 空间复杂度:O(1)。

活动地址:CSDN21天学习挑战赛

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值