Best Time to Buy and Sell Stock

本文介绍了一种通过动态规划算法解决股票买卖问题的方法,旨在找到一次买卖中能获得的最大利润。文章提供了两种解决方案:暴力法和动态规划法,并详细解析了动态规划法的状态转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode-Algorithm-DP-121

题目:
Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
(假定你有一个数组,数组中的每个元素表示元素所在索引的那天的价格。如果你只被允许最多完成一次交易,也就是进行一次买卖,请设计一个算法找到最大的收益。)

例子:
输入:[7, 1, 5, 3, 6, 4].
输出:5.
解释:由于只能进行一次交易,因此在第一天买入和在第4天卖出能得到的收益最大,收益为6-1=5。

输入:[7, 6, 4, 3, 1].
输出:0.
解释:由于卖出日期必须大于买入日期,因此对于当前数组无论怎么样的买卖都不能得到正的收益,因此,最大收益为0。


题解:
方法1:(暴力法)
做容易想的办法就是把所有可能的买卖收益计算出来,然后找出其中的最大值。所谓“可能的买卖”也就是在卖出日期大于等于买入日期的前提下进行所有的一次买卖。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int max = 0;
        for (int i = 0; i < prices.size(); ++i)
            for (int j = i+1; j < prices.size(); ++j)
                max = (max > (prices[j]-prices[i]) ? max : prices[j]-prices[i]);

        return max;
    }
};

分析:
由于要计算出所有索引i和j间且i<=j的差值,因此总的时间复杂度为 O(n2) 。在leetcode上会导致超时。


方法2:(动态规划DP)
虽然不清楚怎么样的买卖组合才能得到最大的收益,但是我们知道,在允许买卖的那天开始(也就是索引为0,第0天)到之后的某一天(第i天),期间的最大收益有两种可能:①到第i天的最大收益就是到第i-1天的收益,也就是说第i天的价格不影响前i-1天的最大收益;②当第i天的价格会影响前i-1天的最大收益时,也就是说在第i天卖出能够得到更大的收益,这时最大收益就是第i天的价格减去前i-1天的最低价格。所以可以通过动态规划解决这个问题。状态转移函数为:f(i)=max{f(i-1), prices[i]-minPrice},其中f(i)表示到第i天为止得到的最大收益,minPrice表示钱i-1天的最低价格。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if (prices.empty()) return 0;

        vector<int> profit;
        int maxPro = 0;
        int minPrice = prices[0];
        profit.push_back(0);

        for (int i = 1; i < prices.size(); ++i) {
            minPrice = min(prices[i], minPrice);
            profit.push_back(max(profit[i-1], prices[i] - minPrice));
            maxPro = max(maxPro, profit[i]);
        }

        return maxPro;
    }
};

分析:
由于算法的整个过程只需要遍历一次prices容器,因此总的时间复杂度为 O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值