LeetCode C++ 121. Best Time to Buy and Sell Stock【Array/Dynamic Programming】简单

本文探讨了在给定股票价格数组的情况下,如何设计算法找出仅进行一次交易的最大利润。通过对比暴力解法与动态规划解法,展示了如何优化算法以避免超时,并给出了C++与Java实现代码。

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

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 (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

题意:最多可以交易一次,求买卖股票得到的最大利润是多少。


解法1 暴力

暴力求解每对下标的差值,找到最大值。结果超出时间限制。具体代码如下:

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

解法2 动态规划

在上面的求解过程中,存在许多重复的子问题。如:

Input : [7,1,5,3,6,4]	  下面都是差值:
maxProfit[0] = 0, p[i] = prices[i]
第一次:  p[1] - p[0]   = maxProfit[1] 
第二次:  max(p[2] - p[1], p[2] - p[0], maxProfit[1]) = maxProfit[2]
第三次:  max(p[3] - p[2], p[3] - p[1], p[3] - p[0], maxProfit[2]) = maxProfit[3]
...

每次求解中,都要分别以当前的价格和前面的所有价格相减(太慢!),求出各差值,然后和之前得到的最大利润比较,从而得到当前的最大利润。

思考一下,就会发现,和前面的所有价格相减没有必要,只需要和前部分中的最小价格相减,就一定可以得到最大差值。然后和之前的最大利润比较即可。于是有了下面的代码:

class Solution {
public:
    int maxProfit(vector<int>& prices) { 
        if (prices.empty()) return 0;  
        //dp[i]为前i天中最多一次交易可得的最大收益
        //前i天的最大收益 = max{前i-1天的最大收益,第i天的股价-前i-1天中的最小股价}
        //dp[i] = max(dp[i - 1], prices[i] - minPrice)
        int mx = 0, mi = prices[0]; //dp[0]=0, 最小的股价=prices[0]
        for (int i = 1; i < prices.size(); ++i) { 
            mx = max(mx, prices[i] - mi); //dp[i]
            mi = min(mi, prices[i]);
        }
        return mx;
    }
};

对应的Java版本如下:

class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length <= 1) return 0;
        int maxprofit = 0, minprice = prices[0];
        //dp[i]是第i天得到的最高利润,只能交易一次,因此此时的最高利润为max(maxProfit, 此时的价格-之前的最低价格)
        for (int i = 1; i < prices.length; ++i) { 
            maxprofit = Math.max(maxprofit, prices[i] - minprice);
            minprice = Math.min(minprice, prices[i]);
        }
        return maxprofit;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

memcpy0

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

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

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

打赏作者

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

抵扣说明:

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

余额充值