77.买卖股票的最佳时机

34 阅读2分钟

题目链接

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

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

解法1 暴力解法

思路

最简单的解法就是两层循环,第二层寻找 i + 1 开始后面的最大值,顺便更新答案。

但这样不能 AC ,只能通过 202 个用例。

代码

function maxProfit(prices: number[]): number {
    let result = 0;

    for (let i = 0; i < prices.length; i++) {
        for (let j = i + 1; j < prices.length; j++) {
            result = Math.max(result, prices[j] - prices[i]);
        }
    }

    return result;
};

时空复杂度

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

空间复杂度:O(1)

解法2 后缀最大值

思路

答案其实寻找的是当前的值和后续的某一个值的最大值,那我们是不是可以通过遍历出后缀数组,即每个 i 的后面的最大值。

这样再次遍历这两个数组,就可以得出最大值的答案。

代码

function maxProfit(prices: number[]): number {
    let result = 0;
    const n = prices.length;
    const suffix = new Array(n).fill(0);

    suffix[n - 1] = prices[n - 1];
    for (let i = n - 2; i >= 0; i--) {
        suffix[i] = Math.max(suffix[i + 1], prices[i]);
    }

    for (let i = 0; i < prices.length; i++) {
        result = Math.max(result, suffix[i] - prices[i]);
    }

    return result;
};

时空复杂度

时间复杂度:O(n)

空间复杂度:O(n)

解法3 前缀最小值

思路

上个方法的思路是用当前 i 后续的最大值减去 prices[i] ,这样需要额外的后缀最大值空间,而我们可不可以省略这个呢?

我们换个思路,当我们得知当前 i 前面的最小值,是不是也可以得出一个差值,我们在遍历中更新这个差值是不是就得到了答案,每次遍历到当前 prices[i] 比前面的最小值 low 小时,我们后续的差值是不会比这个大的,所以需要更新 low

代码

function maxProfit(prices: number[]): number {
    let result = 0;
    let low = prices[0];

    for (let i of prices) {
        result = Math.max(result, i - low);

        if (i < low) {
            low = i;
        }
    }

    return result;
};

时空复杂度

时间复杂度:O(n)

空间复杂度:O(1)