Easy

题目描述

给定一个数组 prices,其中 prices[i] 是一支给定股票第 i 天的价格。

你想通过选择某一天买入一只股票和选择在未来的另一天卖出该股票来最大化你的利润。

返回你从这笔交易中能获取的最大利润。如果你不能获取任何利润,返回 0

示例 1:

输入:prices = [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 <= 10^5
  • 0 <= prices[i] <= 10^4

解题思路

这道题有多种解法思路:

方法一:暴力法(不推荐) 遍历每一对买入卖出的组合,时间复杂度 O(n²),会超时。

方法二:动态规划思路 定义两个状态:持有股票和不持有股票时的最大收益。但对于这道只能交易一次的题目,有更简单的解法。

方法三:一次遍历(推荐) 核心思想是:要想获得最大利润,就要在最低点买入,在最高点卖出。我们可以维护一个最低价格,遍历数组时不断更新这个最低价格,同时计算当前价格与最低价格的差值作为潜在利润,保持记录最大利润。

具体算法:

  1. 初始化最低价格为第一天的价格,最大利润为0
  2. 从第二天开始遍历:
    • 如果当前价格更低,更新最低价格
    • 否则计算当前卖出的利润(当前价格 - 最低价格)
    • 更新最大利润

这种方法只需要一次遍历,时间复杂度O(n),空间复杂度O(1),是最优解法。

代码实现

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minPrice = prices[0];
        int maxProfit = 0;
        
        for (int i = 1; i < prices.size(); i++) {
            if (prices[i] < minPrice) {
                minPrice = prices[i];
            } else {
                maxProfit = max(maxProfit, prices[i] - minPrice);
            }
        }
        
        return maxProfit;
    }
};
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        min_price = prices[0]
        max_profit = 0
        
        for i in range(1, len(prices)):
            if prices[i] < min_price:
                min_price = prices[i]
            else:
                max_profit = max(max_profit, prices[i] - min_price)
        
        return max_profit
public class Solution {
    public int MaxProfit(int[] prices) {
        int minPrice = prices[0];
        int maxProfit = 0;
        
        for (int i = 1; i < prices.Length; i++) {
            if (prices[i] < minPrice) {
                minPrice = prices[i];
            } else {
                maxProfit = Math.Max(maxProfit, prices[i] - minPrice);
            }
        }
        
        return maxProfit;
    }
}
var maxProfit = function(prices) {
    let minPrice = prices[0];
    let maxProfit = 0;
    
    for (let i = 1; i < prices.length; i++) {
        if (prices[i] < minPrice) {
            minPrice = prices[i];
        } else {
            maxProfit = Math.max(maxProfit, prices[i] - minPrice);
        }
    }
    
    return maxProfit;
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n)只需要遍历数组一次
空间复杂度O(1)只使用了常数个额外变量

相关题目