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

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.

最开始nc,只想到了brute force算法。想着最大减最小就是结果,但是如果最大值出现在最小值之前就不能算了。所以想到brute force解法。对于每个数,在它后面找一个最大的数,相减得到的结果作为在这个时候买入的最优结果。最后从所有最优中找到一个最大的。虽然加入了一些优化,但是总体的时间复杂度为O(n^2)。

 1 public int maxProfit(int[] prices) {
 2         if (prices.length == 0) return 0;
 3         int profit = 0;
 4         int lowPrice = prices[0];
 5         for (int i=0; i<prices.length-1; i++) {
 6             if (i>0 && prices[i] >= lowPrice) continue;
 7             for (int j=i+1; j<prices.length; j++) {
 8                 int p = prices[j] - prices[i];
 9                 if ( p > profit) {
10                     profit = p;
11                     lowPrice = prices[i];
12                 }
13             }
14         }
15         return profit;
16     }

后来经点拨,想到用dp思想。比如说我在第i时刻得到的最好的结果可以由之前的结果得到。

ith时刻的最好结果 = max(i-1 时刻最好结果,i与前i-1个元素最小的一个的差)。

后来我一想,不对呀,压根不用重新弄一个profit数组存下每个时刻最优的profit。这个算法只用从前到后扫描一遍。所以时间复杂度O(n)。

 1  public int maxProfit(int[] prices) {
 2         if (prices.length == 0) return 0;
 3         int profit = 0;
 4         int lowestPrice = prices[0];
 5         for (int i=0; i<prices.length; i++) {
 6             if(prices[i] < lowestPrice) {
 7                 lowestPrice = prices[i];
 8                 continue;
 9             }
10             else {
11                 profit = Math.max(profit, prices[i]-lowestPrice);
12             }
13         }
14         
15         return profit;
16     }

 


 

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

这回可以做任意次数的交易。受上一题的影响,我还是用dp。

我先记录下在每一时刻最优的profit。

ith 最大profit = i-j 时刻最大profit + 从j到i做一次交易的最大的profit。

这样感觉时间复杂度是O(n^2).

 1  public int maxProfit(int[] prices) {
 2         if (prices.length == 0) return 0;
 3         int[] profit = new int[prices.length];
 4         for (int i=0; i<prices.length; i++) {
 5             if (i>0 && prices[i] <= prices[i-1]) {
 6                 profit[i] = profit[i-1];
 7                 continue;
 8             }
 9             int pmax = 0;
10             int p = 0;
11             for (int j=0; j<i; j++) {
12                 p = 0;
13                 if (prices[i]-prices[j]>0) p += prices[i] - prices[j];
14                 if (j > 0) p += profit[j-1];
15                 if (p>pmax) pmax = p;
16             }
17             profit[i] = pmax;
18             
19         }
20         return profit[prices.length-1];
21     }

后来经点拨,发现了一个更简单的算法。就在数组中,每一次递增,我都是从初始的时刻买入,最后时刻卖出。这样可以得到每一次价格上升的利润。

这样可以只扫描一次数组,因此时间复杂度为O(n)。

 1 public int maxProfit(int[] prices) {
 2         if (prices.length == 0) return 0;
 3         int profit = 0;
 4         for (int i=1; i<prices.length; i++) {
 5             if (prices[i]>prices[i-1]) {
 6                 profit += prices[i] - prices[i-1];
 7             }
 8         }
 9         return profit;
10     }

但不知道为什么,这样的时间算下来要比第一种要慢。。。

 


Design an algorithm to find the maximum profit. You may complete at most two transactions.

只做两次交易。

我的想法还是用dp。我给每个时刻附两个值,一个是在这个时刻之前只做了一次交易的最大的profit(first),一个是在这之前做了两次交易的最大的profit(second)。first的计算方法和第一题一样,时间复杂度为O(n)。

second[i] = first[j-1] + 从j到i最大的profit。对于任意的j < i.所以算下来时间复杂度应该为O(n^2)。

 1 public int maxProfit(int[] prices) {
 2         if (prices.length == 0) return 0;
 3         
 4         int[] first = new int[prices.length];
 5         int[] second = new int[prices.length];
 6         
 7         int minPrices = prices[0];
 8         for (int i=1; i<prices.length; i++) {
 9             if (prices[i] < minPrices) {
10                 minPrices = prices[i];
11                 first[i] = first[i-1];
12             }
13             else {
14                 first[i] = prices[i] - minPrices;
15             }
16             
17             if(prices[i] < prices[i-1]) {
18                 second[i] = second[i-1];
19                 continue;
20             }
21             else {
22                 int p2 = 0;
23                 int pmax = 0;
24                 for (int j=0; j<i; j++) {
25                     p2 = 0;
26                     if (prices[i] > prices[j]) p2 += prices[i] - prices[j];
27                     if (j>0) p2 += first[j-1];
28                     if (p2 > pmax) pmax = p2;
29                 }
30                 second[i] = pmax;
31             }
32         }
33         
34         return Math.max(first[prices.length-1], second[prices.length-1]);
35     }

但是这个方法在[10000, 9999, 9998, ........]超时了。但是在这种情况下时间复杂度应该为O(n)呀,为啥会超时。。。

后来经点拨,学会了一种O(n)的算法。

上一种解法中second的计算方法就是算[0...j-1][j...i]两段最大的profit相加。但是在算第二段的时候需要遍历[j...i]得到minPrice。

现在我不用计算每一个i对应的[j...i],我用O(n)的算法得到[j...n]的就行了。我想计算[0...n]的最大profit,我分别计算[0...j-1]和[j...n]就行。

[0...j-1]的解法和第一题一样,O(n)。[j...n]和[0...j-1]一样,只是从最后往前算,还是O(n)。所以总的时间复杂度为O(n)。

 1 public int maxProfit(int[] prices) {
 2         if (prices.length < 2) return 0;
 3         int[] profit = new int[prices.length];
 4         int maxProfit = 0;
 5         
 6         int minPrices = prices[0];
 7         for (int i=1; i<prices.length; i++) {
 8             if (prices[i] < minPrices) {
 9                 minPrices = prices[i];
10                 profit[i] = profit[i-1];
11             }
12             else {
13                 profit[i] = Math.max(prices[i] - minPrices, profit[i-1]);
14             }
15         }
16         
17         int maxPrices = prices[prices.length-1];
18         maxProfit = profit[prices.length-1];
19         for (int i=prices.length-1; i>0; i--) {
20             int p = profit[i-1];
21             if (prices[i] > maxPrices) {
22                 maxPrices = prices[i];
23             }
24             else {
25                 p += maxPrices - prices[i]; 
26             }
27             if (p > maxProfit) {
28                 maxProfit = p;
29             }
30         }
31         
32         return maxProfit;
33     }

 

  

 

posted on 2014-01-18 23:58  longhorn  阅读(211)  评论(0编辑  收藏  举报

导航