「LeetCode」121.买卖股票的最佳时机

231 阅读3分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

题目描述🌍

给定一个数组 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 <= prices.length <= 105
  • 0 <= prices[i] <= 104

暴力解法📈

解题思路

该题的意图在于返回给定数组的最大差值,且最大值索引(卖出价格)必须大于最小值索引(买入价格)。

我们直接进行二次遍历暴力求解,但会发现无法通过测试用例:

果然,纯粹暴力求解并不是一种明智/有效率的解法,但也并非不能实现,在内层循环中添加条件 prices[j] > prices[i] 即可勉强通过测试用例。

代码

Java

class Solution {
    public int maxProfit(int[] prices) {
        int length = prices.length;
        int dif = 0;
        for (int i = 0; i < length - 1; i++) {
            for (int j = i + 1; j < length && prices[j] > prices[i]; j++) {
                dif = Math.max(prices[j] - prices[i], dif);
            }
        }
        return dif;
    }
}

C++

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

时间复杂度:O(n2)O(n^2)

空间复杂度:O(1)O(1)

动态规划🚀

解题思路

本题有两个约束条件:

  • 不能在买入股票前卖出股票
  • 最多只允许一笔交易

若想要获得最大的收益,我们就必须找到**目前已知的历史最低股票价格**,然后想象如果今天第 i 天卖出股票,能否比以往的最高收益还高?若可以,更新最高收益 maxProfit,随着时间的推进(股票每天价格不一),有可能会再次更新历史最低股票价格,继续思考上述问题,直到股票交易结束(数组遍历完毕)。这时 maxProfit 存储的即为所求最大收益。

🧩接下来用动图演示下算法具体过程:

代码

Java

class Solution {
    public int maxProfit(int[] prices) {
        int length = prices.length;
        int maxProfit = 0;
        int minPrice = Integer.MAX_VALUE;

        for (int i = 0; i < length; i++) {
            if (prices[i] < minPrice) {
                minPrice = prices[i];
            } else if (prices[i] - minPrice > maxProfit) {
                maxProfit = prices[i] - minPrice;
            }
        }
        return maxProfit;
    }
}

C++

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int length = prices.size();
        int maxProfit = 0;
        // because price[i] <= 10000
        int minPrice = INT16_MAX;
        for (int i = 0; i < length; ++i) {
            minPrice = min(minPrice, prices[i]);
            maxProfit = max(maxProfit, prices[i] - minPrice);
        }
        return maxProfit;
    }
};

时间复杂度:O(n)O(n)

空间复杂度:O(1)O(1)

「DP」系列题目🌓

可用动态规划解决的股票问题系列,做前请熟悉这一类题目的动态规划解题思路

最后🌅

该篇文章为 「LeetCode」 系列的 No.14 篇,在这个系列文章中:

  • 尽量给出多种解题思路
  • 提供题解的多语言代码实现
  • 记录该题涉及的知识点

👨‍💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!