Leetcode121. Best Time to Buy and Sell Stock

Leetcode121. Best Time to Buy and Sell Stock

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.
解法一 暴力

两个循环,外层循环表示买入时候的价格,内层循环表示卖出时候的价格,遍历所有的情况,期间更新最大的收益。

public int maxProfit(int[] prices) {
    int maxProfit = 0;
    for (int i = 0; i < prices.length; i++) {
        for (int j = i + 1; j < prices.length; j++) {
            maxProfit = Math.max(maxProfit, prices[j] - prices[i]);
        }
    }
    return maxProfit;
}
解法二 双指针

双重循环的优化,经常就是考虑双指针的方法,从而使得两层循环变成一层。

用两个指针, buy 表示第几天买入,sell 表示第几天卖出
开始 buy,sell 都指向 0,表示不操作
3 6 7 2 9
^
b
^
s

sell 后移表示这天卖出,计算收益是 6 - 3 = 3
3 6 7 2 9
^ ^
b s


sell 后移表示这天卖出,计算收益是 7 - 3 = 4
3 6 7 2 9
^   ^
b   s

sell 后移表示这天卖出,计算收益是 2 - 3 = -1
3 6 7 2 9 12
^     ^
b     s

此外,如上图,当前 sell 指向的价格小于了我们买入的价格,所以我们要把 buy 指向当前 sell 才会获得更大的收益
原因很简单,收益的价格等于 prices[sell] - prices[buy],buy 指向 sell 会使得减数更小,
所以肯定要选更小的 buy
3 6 7 2 9 12
      ^
      s
      ^
      b


sell 后移表示这天卖出,计算收益是 9 - 2 = 7
这里也可以看出来减数从之前的 3 变成了 2,所以收益会更大
3 6 7 2 9 12
      ^ ^
      b s

sell 后移表示这天卖出,计算收益是 12 - 2 = 10
3 6 7 2 9 12
      ^   ^
      b   s

然后在这些价格里选最大的就可以了。
public int maxProfit(int[] prices) {
    int maxProfit = 0;
    int buy = 0;
    int sell = 0;
    for (; sell < prices.length; sell++) {
        //当前价格更小了,更新 buy
        if (prices[sell] < prices[buy]) {
            buy = sell;
        } else {
            maxProfit = Math.max(maxProfit, prices[sell] - prices[buy]);

        }
    }
    return maxProfit;
}
动态规划

对于数组 1 6 2 8,代表股票每天的价格。

定义一下转换规则,当前天的价格减去前一天的价格,第一天由于没有前一天,规定为 0,用来代表不操作。

数组就转换为 0 6-1 2-6 8-2,也就是 0 5 -4 6。现在的数组的含义就变成了股票相对于前一天的变化了。

现在我们只需要找出连续的和最大是多少就可以了,也就是变成了 Leetcode53. 求子序列最大的和

这个思想的本质是买入卖出和连续的和形成了互相映射

public int maxProfit(int[] prices) {
    int n = prices.length;
    int dp = 0;
    int max = 0;
    for (int i = 1; i < n; i++) {
        int num = prices[i] - prices[i - 1];
        dp = Math.max(dp + num, num);
        max = Math.max(max, dp);
    }
    return max;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值