【动态规划-1】121.买卖股票的最佳时机

题目描述:

给定一个数组 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. 维护历史最低价格 minPrice

  2. 每天计算 prices[i] - minPrice,更新最大利润

  3. 更新 minPrice = min(minPrice, prices[i])

具体过程示例:

prices = [7,1,5,3,6,4]

i pricesi minPrice 当天利润 maxProfit
0 7 7 0 0
1 1 1 0 0
2 5 1 4 4
3 3 1 2 4
4 6 1 5 5
5 4 1 3 5

结果:5 ✅

代码实现:

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minPrice = INT_MAX;
        int maxProfit = 0;
        
        for (int price : prices) {
            if (price < minPrice) {
                minPrice = price;  // 更新最低价格
            } else {
                maxProfit = max(maxProfit, price - minPrice);  // 更新最大利润
            }
        }
        
        return maxProfit;
    }
};

更简洁的写法:

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minPrice = INT_MAX, maxProfit = 0;
        for (int price : prices) {
            minPrice = min(minPrice, price);
            maxProfit = max(maxProfit, price - minPrice);
        }
        return maxProfit;
    }
};

复杂度分析:

维度 复杂度 说明
时间复杂度 O(n) 一次遍历
空间复杂度 O(1) 只用两个变量

关键细节:

  1. 为什么 maxProfit 初始为 0?

因为如果股票一直跌,不买就是最大利润(0),不会亏本。

  1. 为什么先更新 minPrice 再计算利润?

因为买入必须在卖出之前。先更新 minPrice 保证用的是今天之前的最低价格。

cpp

复制代码
minPrice = min(minPrice, price);        // 先更新最低价
maxProfit = max(maxProfit, price - minPrice);  // 再算利润

如果反过来,可能会用当天的价格买入和卖出,利润为 0,逻辑不对。

  1. 和「买卖股票的最佳时机 II」的区别
题目 区别
121. 买卖股票 I 只能买卖一次
122. 买卖股票 II 可以买卖多次

122 题:只要后一天比前一天高,就累加利润。

方法二:动态规划

思路:

维护两个状态:

  • dp[i][0]:第 i 天不持有股票的最大利润

  • dp[i][1]:第 i 天持有股票的最大利润

代码实现:

复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(2, 0));
        
        dp[0][0] = 0;             // 不持有
        dp[0][1] = -prices[0];    // 持有(买入)
        
        for (int i = 1; i < n; i++) {
            dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);  // 卖出
            dp[i][1] = max(dp[i-1][1], -prices[i]);              // 买入
        }
        
        return dp[n-1][0];
    }
};

空间优化:

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int hold = -prices[0];  // 持有股票
        int notHold = 0;        // 不持有股票
        
        for (int i = 1; i < prices.size(); i++) {
            notHold = max(notHold, hold + prices[i]);  // 卖出
            hold = max(hold, -prices[i]);              // 买入
        }
        
        return notHold;
    }
};

复杂度:时间 O(n),空间 O(1)

两种方法对比:

方法 时间复杂度 空间复杂度 推荐度
贪心(维护最低价) O(n) O(1) ⭐⭐⭐⭐⭐
动态规划 O(n) O(1) ⭐⭐⭐⭐

总结:

要点 说明
核心思想 维护历史最低价,每天计算利润
关键操作 minPrice = min(minPrice, price); maxProfit = max(maxProfit, price - minPrice);
时间复杂度 O(n)
空间复杂度 O(1)
相关推荐
名不经传的养虾人1 小时前
从0到1:企业级AI项目迭代日记 Vol.117|学会忘记,学会证明,学会设边界
大数据·人工智能·算法·企业ai·多agent协作
水饺编程1 小时前
第1章,[Win32 章节]:API 及 内存管理模式
c语言·c++·windows·visual studio
weixin_307779131 小时前
C++代码实现MATLAB中的cvpartition函数功能
开发语言·c++·算法·matlab
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出优秀项目组中的“独特编号“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
(Charon)2 小时前
【C++面试】线程同步机制:互斥锁、条件变量、原子操作与读写锁
开发语言·c++·算法·面试
七牛云行业应用2 小时前
刚刚!GPT-6.1 Sol Ultrafast 上线:速度、价格、API 接入全指南
算法
Omics Pro2 小时前
研究证实AI虚拟细胞可用于药物靶点发现
数据库·人工智能·算法·机器学习·自然语言处理
在所不辞兄2 小时前
常微分方程详解与应用
人工智能·神经网络·算法·机器学习
-dzk-2 小时前
【动态规划】LC 416.分割等和子集
算法·动态规划·代理模式