买卖股票的最佳时机2-题解

买卖股票的最佳时机 II

问题描述

给定一个数组 prices,其中 prices[i] 表示某只股票第 i 天的价格。你可以多次交易(买入和卖出股票),但在任何时候最多只能持有一股股票。你也可以在同一天买入并卖出股票。

目标:计算你所能获得的最大利润

示例
  • 示例 1

    输入:prices = [7,1,5,3,6,4]
    输出:7
    解释:
    - 第 2 天买入(价格 = 1),第 3 天卖出(价格 = 5),利润 = 5 - 1 = 4。
    - 第 4 天买入(价格 = 3),第 5 天卖出(价格 = 6),利润 = 6 - 3 = 3。
    - 总利润 = 4 + 3 = 7。
    
  • 示例 2

    输入:prices = [1,2,3,4,5]
    输出:4
    解释:
    - 第 1 天买入(价格 = 1),第 5 天卖出(价格 = 5),利润 = 5 - 1 = 4。
    - 总利润 = 4。
    
  • 示例 3

    输入:prices = [7,6,4,3,1]
    输出:0
    解释:
    - 在这种情况下,没有交易可以获得正利润,所以最大利润为 0。
    
解题思路
  • 贪心算法:由于可以多次交易,我们可以采用贪心算法,只要今天的价格高于昨天的价格,就进行买卖操作,从而累加所有的利润。

  • 关键点

    • 持股限制:在任何时候最多只能持有一股股票。
    • 当天买卖:可以在同一天买入并卖出股票。
  • 实现思路

    • 遍历价格数组,从第 1 天开始(索引为 1)。
    • 比较当天价格和前一天价格的差值:
      • 如果差值大于 0,说明价格上涨,可以获得利润。
      • 将差值累加到总利润中。
    • 遍历结束后,返回总利润。
算法步骤
  1. 初始化变量

    • totalProfit = 0:用于累加总利润。
  2. 遍历价格数组

    • 从索引 i = 1 开始,直到 prices.length - 1
    • 对于每个 i,计算 profit = prices[i] - prices[i - 1]
      • 如果 profit > 0,则将 profit 加到 totalProfit 中。
  3. 返回结果

    • 遍历完成后,返回 totalProfit,即最大利润。
代码解释
function maxProfit(prices: number[]): number {
    let totalProfit = 0; // 初始化总利润

    for (let i = 1; i < prices.length; i++) {
        const profit = prices[i] - prices[i - 1]; // 计算当天与前一天的价格差
        if (profit > 0) {
            totalProfit += profit; // 如果有利润,累加到总利润中
        }
    }

    return totalProfit; // 返回总利润
}
  • 变量初始化

    • totalProfit:用于累加所有的正利润。
  • 遍历数组

    for (let i = 1; i < prices.length; i++) {
        ...
    }
    
    • 从第二天开始遍历,因为需要与前一天的价格比较。
  • 计算利润并累加

    const profit = prices[i] - prices[i - 1];
    if (profit > 0) {
        totalProfit += profit;
    }
    
    • 计算当天价格与前一天价格的差值。
    • 如果差值大于 0,表示价格上涨,可以获得利润,将其累加到 totalProfit
  • 返回结果

    return totalProfit;
    
示例演示

prices = [7,1,5,3,6,4] 为例:

  • 初始化

    • totalProfit = 0
  • 遍历过程

    1. i = 1

      • prices[1] - prices[0] = 1 - 7 = -6,利润为负,跳过。
    2. i = 2

      • prices[2] - prices[1] = 5 - 1 = 4,利润为正,totalProfit += 4totalProfit = 4
    3. i = 3

      • prices[3] - prices[2] = 3 - 5 = -2,利润为负,跳过。
    4. i = 4

      • prices[4] - prices[3] = 6 - 3 = 3,利润为正,totalProfit += 3totalProfit = 7
    5. i = 5

      • prices[5] - prices[4] = 4 - 6 = -2,利润为负,跳过。
  • 结果

    • totalProfit = 7
时间和空间复杂度分析
  • 时间复杂度:O(n),其中 n 是价格数组的长度。需要遍历一次数组。

  • 空间复杂度:O(1),只使用了常数级别的额外空间。

边界情况处理
  • 价格单调递增

    • 例如 prices = [1,2,3,4,5],总利润为 4
  • 价格单调递减

    • 例如 prices = [7,6,5,4,3],无法获得正利润,totalProfit = 0
  • 价格数组长度为 1 或 0

    • 无法进行交易,利润为 0
与问题一的区别
  • 在第一题(只能进行一次交易)中,我们需要找到一个最佳的买入和卖出时机,以获得最大利润。

  • 在本题中(可以多次交易),我们可以多次买卖股票,只要有利润就进行交易。

扩展
  • 限制交易次数:如果限制交易次数为 k,需要使用动态规划来解决。

  • 增加手续费:如果每次交易需要支付手续费,需要在计算利润时减去手续费。

测试代码
function testMaxProfit() {
    const testCases = [
        { prices: [7, 1, 5, 3, 6, 4], expected: 7 },
        { prices: [1, 2, 3, 4, 5], expected: 4 },
        { prices: [7, 6, 4, 3, 1], expected: 0 },
        { prices: [1, 2, 1, 2, 1, 2], expected: 3 },
    ];

    for (let { prices, expected } of testCases) {
        const result = maxProfit(prices);
        console.assert(result === expected, `测试失败:输入 ${prices},期望输出 ${expected},实际输出 ${result}`);
    }

    console.log("所有测试用例通过!");
}

testMaxProfit();

总结

  • 核心思想:只要今天的价格高于昨天的价格,就买入并卖出,累加所有正利润。

  • 贪心策略:局部最优解(每次有利润就交易)能够得到全局最优解(最大总利润)。

  • 实现简单:代码简洁明了,易于理解和实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李学软件

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值