LeetCode:Best Time to Buy and Sell Stock I II III


LeetCode: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.

分析:題目的意思是整個過程中只能買一只股票然后賣出,也可以不買股票。也就是我們要找到一對最低價和最高價,最低價在最高價前面,以最低價買入股票,以最低價賣出股票。

下面三個算法時間復雜度都是O(n)

算法1:順序掃描股票價格,找到股票價格的第一個上升區間,以區間最低價買入,最高價賣出,后面掃描到上升區間時,根據區間的邊界更新最低價和最高價                                                    本文地址

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int i = 0;
 9         int ibuy = 0, isell = 0, leastBuy;
10         bool setted = false;
11         while(i < len - 1)
12         {
13             int buy, sell;
14             while(i+1 < len && prices[i+1] < prices[i])i++;//遞減區間
15             buy = i++;
16                 
17             while(i < len && prices[i] >= prices[i-1])i++;//遞增區間
18             sell = i-1;
19             if(setted == false)
20             {
21                 ibuy = buy;
22                 isell = sell;
23                 leastBuy = buy;
24                 setted = true;
25             }
26             else
27             {
28                 if(prices[buy] <= prices[ibuy] && prices[sell] - prices[buy] >= prices[isell] - prices[ibuy])
29                     {ibuy = buy; isell = sell;}
30                 if(prices[sell] > prices[isell] && prices[buy] > prices[leastBuy])
31                     {isell = sell; ibuy = leastBuy;}
32                 if(prices[leastBuy] > prices[buy])leastBuy = buy;
33             }
34         }
35         return prices[isell] - prices[ibuy];
36     }
37 };
View Code

@dslztx在評論中找出了上面算法的一個錯誤,修正如下

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int i = 0;
 9         int ibuy = 0, isell = 0, leastBuy = 0; //leastBuy為前面已經掃描過的最低價格
10         bool setted = false;
11         while(i < len - 1)
12         {
13             int buy, sell;
14             while(i+1 < len && prices[i+1] < prices[i])i++;//遞減區間
15             buy = i++;
16 
17             while(i < len && prices[i] >= prices[i-1])i++;//遞增區間
18             sell = i-1;
19             //此時從prices[buy]~prices[sell]是遞增區間
20 
21             if(prices[buy] <= prices[ibuy])
22             {
23                 if(prices[sell] - prices[buy] >= prices[isell] - prices[ibuy])
24                 {
25                     ibuy = buy;
26                     isell = sell;
27                 }
28             }
29             else
30             {
31                 if(prices[sell] > prices[isell])
32                     isell = sell;
33             }
34             if(prices[buy] > prices[leastBuy])
35                 ibuy = leastBuy;
36 
37             if(prices[leastBuy] > prices[buy])leastBuy = buy;
38         }
39         return prices[isell] - prices[ibuy];
40     }
41 };
View Code

 

算法2:設dp[i]是[0,1,2...i]區間的最大利潤,則該問題的一維動態規划方程如下

dp[i+1] = max{dp[i], prices[i+1] - minprices}  ,minprices是區間[0,1,2...,i]內的最低價格

我們要求解的最大利潤 = max{dp[0], dp[1], dp[2], ..., dp[n-1]} 代碼如下:

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int res = prices[1] - prices[0], minprice = prices[0];
 9         for(int i = 2; i < len; i++)
10         {
11             minprice = min(prices[i-1], minprice);
12             if(res < prices[i] - minprice)
13                 res = prices[i] - minprice;
14         }
15         if(res < 0)return 0;
16         else return res;
17     }
18 };

算法3:按照股票差價構成新數組 prices[1]-prices[0], prices[2]-prices[1], prices[3]-prices[2], ..., prices[n-1]-prices[n-2]。求新數組的最大子段和就是我們求得最大利潤,假設最大子段和是從新數組第 i 到第 j 項,那么子段和= prices[j]-prices[j-1]+prices[j-1]-prices[j-2]+...+prices[i]-prices[i-1] = prices[j]-prices[i-1], 即prices[j]是最大價格,prices[i-1]是最小價格,且他們滿足前后順序關系。代碼如下:

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int res = 0, currsum = 0;
 9         for(int i = 1; i < len; i++)
10         {
11             if(currsum <= 0)
12                 currsum = prices[i] - prices[i-1];
13             else
14                 currsum += prices[i] - prices[i-1];
15             if(currsum > res)
16                 res = currsum;
17         }
18         return res;
19     }
20 };

這個題可以參考here


 

LeetCode: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).

分析:在上一題的基礎上,可以買賣多次股票,但是不能連續買股票,也就是說手上最多只能有一只股票(注意:可以在同一天賣出手上的股票然后再買進)                                                            本文地址

算法1:找到所有價格的遞增區間,每個區間內以對低價買入最高價賣出

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int i = 0;
 9         int res = 0;
10         while(i < len - 1)
11         {
12             int buy, sell;
13             //遞減區間
14             while(i+1 < len && prices[i+1] < prices[i])i++;
15             buy = i++;
16             //遞增區間
17             while(i < len && prices[i] >= prices[i-1])i++;
18             sell = i-1;
19             res += prices[sell] - prices[buy];
20         }
21         return res;
22     }
23 };

算法2:同上一題構建股票差價數組,把數組中所有差價為正的值加起來就是最大利潤了。其實這和算法1差不多,因為只有遞增區間內的差價是正數,並且同一遞增區間內所有差價之和 = 區間最大價格 -  區間最小價格

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         int len = prices.size();
 7         if(len <= 1)return 0;
 8         int res = 0;
 9         for(int i = 0; i < len-1; i++)
10             if(prices[i+1]-prices[i] > 0)
11                 res += prices[i+1] - prices[i];
12         return res;
13     }
14 };

 


 

LeetCode:Best Time to Buy and Sell Stock III

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 at most two transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

分析:這一題約束最多只能買賣兩次股票,並且手上最多也只能持有一支股票。因為不能連續買入兩次股票,所以買賣兩次肯定分布在前后兩個不同的區間。設p(i) = 區間[0,1,2...i]的最大利潤 + 區間[i,i+1,....n-1]的最大利潤(式子中兩個區間內分別只能有一次買賣,這就是第一道題的問題),那么本題的最大利潤 = max{p[0],p[1],p[2],...,p[n-1]}。根據第一題的算法2,我們可以求區間[0,1,2...i]的最大利潤;同理可以從后往前掃描數組求區間[i,i+1,....n-1]的最大利潤,其遞歸式如下:

dp[i-1] = max{dp[i], maxprices - prices[i-1]}  ,maxprices是區間[i,i+1,...,n-1]內的最高價格。                                                                                      本文地址

因此兩趟掃描數組就可以解決這個問題,代碼如下:

 1 class Solution {
 2 public:
 3     int maxProfit(vector<int> &prices) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         const int len = prices.size();
 7         if(len <= 1)return 0;
 8         int maxFromHead[len];
 9         maxFromHead[0] = 0;
10         int minprice = prices[0], maxprofit = 0;
11         for(int i = 1; i < len; i++)
12         {
13             minprice = min(prices[i-1], minprice);
14             if(maxprofit < prices[i] - minprice)
15                 maxprofit = prices[i] - minprice;
16             maxFromHead[i] = maxprofit;
17         }
18         int maxprice = prices[len - 1];
19         int res = maxFromHead[len-1];
20         maxprofit = 0;
21         for(int i = len-2; i >=0; i--)
22         {
23             maxprice = max(maxprice, prices[i+1]);
24             if(maxprofit < maxprice - prices[i])
25                 maxprofit = maxprice - prices[i];
26             if(res < maxFromHead[i] + maxprofit)
27                 res = maxFromHead[i] + maxprofit;
28         }
29         return res;
30     }
31 };

【版權聲明】轉載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3436457.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM