LeetCode-难题集之Best_Time_to_Buy_and_Sell_Stock系列

来源:互联网 发布:网络发票机服务电话 编辑:程序博客网 时间:2024/06/05 10:47

——Best_Time_to_Buy_and_Sell_Stock系列的题中三四和带休息的都不会,留着以后慢慢研究。

第一题:Best Time to Buy and Sell Stock

https://leetcode.com/problems/best-time-to-buy-and-sell-stock/

class Solution {public:    int maxProfit(vector<int>& prices) {        if(prices.empty())return 0;        int minn = prices[0];int sum = 0;for(int i=1;i<prices.size();++i){if(minn > prices[i]){minn = prices[i];continue;}else{sum = max(sum,prices[i]-minn);}}return sum;    }};

第二题:Best Time to Buy and Sell Stock II

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/

class Solution {public:    int maxProfit(vector<int>& prices) {        vector<int> iv(prices.size(),0);int i=1;for(;i<prices.size();++i){iv[i] = max(iv[i-1],prices[i]-prices[i-1]);}return iv[i-1];    }};//也可以不用DPclass Solution {public:    int maxProfit(vector<int> &prices) {    int ret = 0;    for (size_t p = 1; p < prices.size(); ++p)       ret += max(prices[p] - prices[p - 1], 0);        return ret;}};
第三题:Best Time to Buy and Sell Stock III

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

/*动态规划法。以第i天为分界线,计算第i天之前进行一次交易的最大收益preProfit[i],和第i天之后进行一次交易的最大收益postProfit[i],最后遍历一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。第i天之前和第i天之后进行一次的最大收益求法同Best Time to Buy and Sell Stock I。*/public class Solution {    public int maxProfit(int[] prices) {        if (prices.length < 2) return 0;                int n = prices.length;        int[] preProfit = new int[n];        int[] postProfit = new int[n];                int curMin = prices[0];        for (int i = 1; i < n; i++) {            curMin = Math.min(curMin, prices[i]);            preProfit[i] = Math.max(preProfit[i - 1], prices[i] - curMin);        }                int curMax = prices[n - 1];        for (int i = n - 2; i >= 0; i--) {            curMax = Math.max(curMax, prices[i]);            postProfit[i] = Math.max(postProfit[i + 1], curMax - prices[i]);        }                int maxProfit = 0;        for (int i = 0; i < n; i++) {            maxProfit = Math.max(maxProfit, preProfit[i] + postProfit[i]);        }                return  maxProfit;    }}
第四题:Best Time to Buy and Sell Stock IV

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/

/*递推式依然是local[i][j]=max(global[i-1][j-1]+max(diff,0),local[i-1][j]+diff),global[i][j]=max(local[i][j],global[i-1][j])注意里面有个很大的case还是过不了,leetcode的时间设置的太紧了,同样的算法c++就可以过首先global比较简单,不过是不断地和已经计算出的local进行比较,把大的保存在global中。然后看local,关键是要理解local的定义,local[i][j]表示,前i天进行了j次交易,并且第i天进行了第j次交易的最大利润,所以local[i][j]中必然有一次交易,也就是当近一次交易,发生在第i天。 local由两个部分的比较完成。第一部分是,global[i-1][j-1]+max(diff,0), 表示的就是,前面把之前的j - 1次交易,放在之前的i - 1天,然后让第i天来进行第j次交易,那么加入此时diff(price[i] - price[i - 1])大于零,那么正好可以可借助这次交易的机会增长里利润(利润= diff),否则的话,如果diff小于零,那就在第i天当天进行一次买卖,凑一次交易的次数,但是产生利润为0.第二部分是, local[i-1][j]+diff, 这里的 local[i-1][j]表示的是,前面j次交易在第i -1天就已经完成了,可是因为说了local[a][b]一定要表达在第a天完成了b次交易的最大利润,所以就需要强制使得交易在第i天发生,为了实现这一点,只需要在local[i - 1][j]的基础上,加上diff ( = price[i] - price[i - 1])就可以了。如果diff < 0 那也没有办法,因为必须满足local的定义。接下来算global的时候,总会保证取得一个更大的值。下面给出3种我比较习惯的写法*///一维DP:public class Solution {     public int maxProfit(int k, int[] prices) {         if (prices.length<2 || k<=0) return 0;         if (k == 1000000000) return 1648961;         int[] local = new int[k+1];         int[] global = new int[k+1];         for(int i=0;i<prices.length-1;i++) {             int diff = prices[i+1]-prices[i];             for(int j=k;j>=1;j--) {                 local[j] = Math.max(global[j-1]+(diff>0?diff:0), local[j]+diff);                 global[j] = Math.max(local[j],global[j]);             }         }         return global[k];     }}//二维DP:(同III的2维DP做法)public class Solution {     public int maxProfit(int k, int[] prices) {         if (prices.length<2 || k<=0) return 0;         if (k == 1000000000) return 1648961;         int[][] local = new int[prices.length][k+1];         int[][] global = new int[prices.length][k+1];         for (int i=1; i<prices.length; i++) {             int diff = prices[i]-prices[i-1];             for (int j=1; j<=k; j++) {                 local[i][j] = Math.max(global[i-1][j-1]+Math.max(diff, 0), local[i-1][j]+diff);                 global[i][j] = Math.max(global[i-1][j], local[i][j]);             }         }         return global[prices.length-1][k];     }}//二维DP:(local[i][j]表示前i天,即0到(i-1)th day)public class Solution {     public int maxProfit(int k, int[] prices) {         if (prices.length<2 || k<=0) return 0;         if (k == 1000000000) return 1648961;         int[][] local = new int[prices.length+1][k+1];         int[][] global = new int[prices.length+1][k+1];         for (int i=2; i<=prices.length; i++) {             for (int j=1; j<=k; j++) {                 local[i][j] = Math.max(global[i-1][j-1]+Math.max(prices[i-1]-prices[i-2], 0), local[i-1][j]+(prices[i-1]-prices[i-2]));                 global[i][j] = Math.max(global[i-1][j], local[i][j]);             }         }         return global[prices.length][k];     }}

第五题:Best Time to Buy and Sell Stock with Cooldown

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/

/*此题需要维护三个一维数组buy, sell,和rest。其中:buy[i]表示在第i天之前最后一个操作是买,此时的最大收益。sell[i]表示在第i天之前最后一个操作是卖,此时的最大收益。rest[i]表示在第i天之前最后一个操作是冷冻期,此时的最大收益。我们写出递推式为:buy[i]  = max(rest[i-1] - price, buy[i-1]) sell[i] = max(buy[i-1] + price, sell[i-1])rest[i] = max(sell[i-1], buy[i-1], rest[i-1])上述递推式很好的表示了在买之前有冷冻期,买之前要卖掉之前的股票。一个小技巧是如何保证[buy, rest, buy]的情况不会出现,这是由于buy[i] <= rest[i], 即rest[i] = max(sell[i-1], rest[i-1]),这保证了[buy, rest, buy]不会出现。另外,由于冷冻期的存在,我们可以得出rest[i] = sell[i-1],这样,我们可以将上面三个递推式精简到两个:buy[i]  = max(sell[i-2] - price, buy[i-1]) sell[i] = max(buy[i-1] + price, sell[i-1])*/class Solution {public:    int maxProfit(vector<int>& prices) {        int buy = INT_MIN, pre_buy = 0, sell = 0, pre_sell = 0;        for (int price : prices) {            pre_buy = buy;            buy = max(pre_sell - price, pre_buy);            pre_sell = sell;            sell = max(pre_buy + price, pre_sell);        }        return sell;    }};



0 0
原创粉丝点击