121. Best Time to Buy and Sell Stock

题目描述和难度

  • 题目描述:

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

思路分析

求解关键:在最多只允许交易一次的情况下,要求出一段时间内的最大利润,我们只需找到股价最低的一天买进,然后在股价最高的一天卖出即可(并且要满足先买后卖的规则)。因此我们可以在遍历的时候记录之前遍历的最小值,用当前值减去这个最小值,从中取最大。

我们写出了参考解答 1 以后,发现下面这两行代码第 1 行求最大值,第 2 行求最小值,于是我们想能不能把它们的结构统一起来。

maxProfit = Integer.max(maxProfit, prices[i] - preMinimum);
preMinimum = Integer.min(preMinimum, prices[i]);

我们要求利润最大化,因此,我们的方向是把 min 改成 max,很简单,取个负号就行了。其含义也很直观, 0 - price 就表示当前以及之前假如我执行了买操作我的利润,我肯定是还是希望我的利润越来越大。

而我如果执行了卖操作,这个值是和买操作相关的,很容易我们就写出了下面的两行代码,并且,这个操作可以从索引为 0 开始。接下来设置初始值就比较关键了,如果我是买操作,最差我一直卖,所以初始值是整数的最小值;如果我是卖操作,最差我不赚钱,所以下界就是 0。

// 在当前以及之前如果执行了买操作,能够得到的利润的最大值
buy = Integer.max(buy, -price);
// 在当前以及之前如果执行了卖操作,能够得到的利润的最大值
sell = Integer.max(sell, buy + price);

完整代码就是:

int buy = Integer.MIN_VALUE;
int sell = 0;
for (int price : prices) {
    buy = Integer.max(buy, -price);
    sell = Integer.max(sell, buy + price);
}
return sell;
  • 可以用这个思路,解 LeetCode 第 123 题。

参考解答

参考解答1

public class Solution {

    /**
     * 在遍历的时候,记录之前遍历到的元素的最小值
     *
     * @param prices
     * @return
     */
    public int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 0) {
            return 0;
        }
        int maxProfit = 0;
        // 之前遍历到的所有元素的最小值
        int preMinimum = prices[0];
        // 从索引为 1 的元素开始
        for (int i = 1; i < len; i++) {
            // 当前值减去之前遍历到的元素的最小值,从中取出最大,即为所求
            maxProfit = Integer.max(maxProfit, prices[i] - preMinimum);
            preMinimum = Integer.min(preMinimum, prices[i]);
        }
        return maxProfit;
    }
}

参考解答2

public class Solution2 {

    public int maxProfit(int[] prices) {
        int buy = Integer.MIN_VALUE;
        int sell = 0;
        for (int price : prices) {
            buy = Integer.max(buy, -price);
            sell = Integer.max(sell, buy + price);
        }
        return sell;
    }

    public static void main(String[] args) {
        int[] prices = {7, 1, 5, 3, 6, 4};
        Solution2 solution2 = new Solution2();
        int maxProfit = solution2.maxProfit(prices);
        System.out.println(maxProfit);
    }
}

本篇文章的地址为 https://liweiwei1419.github.io/leetcode-solution/leetcode-0121-best-time-to-buy-and-sell-stock ,如果我的题解有错误,或者您有更好的解法,欢迎您告诉我 liweiwei1419@gmail.com