[leetcode] Best Time to Buy and Sell Stock I, II, III, with cool down

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

Example 1:

Input: [7, 1, 5, 3, 6, 4]
Output: 5

max. difference = 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

In this case, no transaction is done, i.e. max profit = 0.

 

 

找到元素i之前的最小值,prices[i] 减去这个最小值就是在元素i是卖出的最大利润,最小值由DP得到,从0扫到length - 1不断更新最大值可以得到最终结果
122. Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

最简单最快的办法,是result += Math.max(prices[i] - prices[i - 1], 0) 从i=0扫到i=length-1一旦有获利就买进卖出

但是这两种求解I II的方法不能沿用到III,VI和cooldown里

 

 

介绍一种可以沿用的方法

对于问题I

维护两个变量:release和hold,release表示如果在i或者i之前卖出的最大值(即i的时候不持有股票),hold表示在i时持有股票的最大值。

recurrent state是hold= Math.max(hold, - prices[i]), release= Math.max(release, hold+ prices[i])

这时有两个问题,一个是initial state是怎样的?另一个是先更新release还是先更新hold?

第二个问题:其实release和hold是同时更新的,因为release的值要借助前一个hold的值,所以先更新release再更新hold

初始的话,hold是Integer.MIN_VALUE, release是0

对于问题II

由于交易次数不限,所以

hold = Math.max(hold, release-prices[i]), release = Math.max(release, hold+prices[i])

这里的更新顺序就比较有意思了,先更新release再更新hold可以通过所有测试点,先储存他们的值每次都用上一次的值更新也可以通过所有测试(我觉得这种对的话很说的过去)

public class Solution {
    public int maxProfit(int[] prices) {
        int release = 0;
        int get = Integer.MIN_VALUE;
        int result = 0;
        for (int price : prices) {
            release = Math.max(release, get + price);
            get = Math.max(get, release - price);
            if (release > result)
                result = release;
        }
        return result;  
    }
}
public class Solution {
    public int maxProfit(int[] prices) {
        int release = 0;
        int get = Integer.MIN_VALUE;
        int result = 0;
        for (int price : prices) {
            int a = release;
            int b = get;
            release = Math.max(a, b + price);
            get = Math.max(b, a - price);
            if (release > result)
                result = release;
        }
        return result;  
    }
}

理解了对于问题I的解法,问题III就很好做了,就是多两个变量,代表第二次交易hold和第二次交易release,问题VI和问题III一样

with cool down也很好做了,就是要根据前天的数据来判断而不是昨天的数据来判断

 

如果都用这种方法来思考的话,所有这些题的答案如下:

I:

public class Solution {
    public int maxProfit(int[] prices) {
        int release = 0;
        int get = Integer.MIN_VALUE;
        for (int price : prices) {
            release = Math.max(release, get + price);
            get = Math.max(get, - price);
        }
        return release;  
    }
}

II:

public class Solution {
    public int maxProfit(int[] prices) {
        int release = 0;
        int get = Integer.MIN_VALUE;
        for (int price : prices) {
            int a = release;
            int b = get;
            release = Math.max(a, b + price);
            get = Math.max(b, a - price);
        }
        return release;  
    }
}
public class Solution {
    public int maxProfit(int[] prices) {
        int release = 0;
        int get = Integer.MIN_VALUE;
        for (int i = 0; i < prices.length; i++) {
            release = Math.max(release, get + prices[i]);
            get = Math.max(get, release - prices[i]);
        }
        return release;  
    }
}

III:

public class Solution {
    public int maxProfit(int[] prices) {
        int hold1 = Integer.MIN_VALUE;
        int release1 = 0;
        int hold2 = Integer.MIN_VALUE;
        int release2 = 0;
        for (int price : prices) {
            release2 = Math.max(hold2 + price, release2);
            hold2 = Math.max(release1 - price, hold2);
            release1 = Math.max(release1, hold1 + price);
            hold1 = Math.max(hold1, - price);
        }
        return release2;
    }
}

VI:

public class Solution {
    public int maxProfit(int k, int[] prices) {
        if (k >= prices.length / 2) {
            int hold = Integer.MIN_VALUE;
            int release = 0;
            for (int price : prices) {
                release = Math.max(release, hold + price);
                hold = Math.max(hold, release - price);
            }
            return release;
        }
        int[] hold = new int[k + 1];
        int[] release = new int[k + 1];
        Arrays.fill(hold, Integer.MIN_VALUE);
        Arrays.fill(release, 0);
        for (int price : prices) {
            for (int i = 1; i <= k; i++) {
                release[i] = Math.max(release[i], hold[i] + price);
                hold[i] = Math.max(hold[i], release[i - 1] - price);
            }
        }
        return release[k];
    }
}

with cool down:

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length < 2) return 0;
        int[] hold = new int[prices.length];
        int[] release = new int[prices.length];
        hold[0] = -prices[0];
        hold[1] = Math.max(-prices[0], -prices[1]);
        release[0] = 0;
        release[1] = Math.max(0, prices[1] - prices[0]);
        for (int i = 2; i < prices.length; i++) {
            release[i] = Math.max(hold[i - 1] + prices[i], release[i - 1]);
            hold[i] = Math.max(hold[i - 1], release[i - 2] - prices[i]);
        }
        return release[prices.length - 1];
    }
}

 

 

 

转载于:https://www.cnblogs.com/Gryffin/p/6295402.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值