1. 程式人生 > >LeetCode——Best Time to Buy and Sell Stock II

LeetCode——Best Time to Buy and Sell Stock II

股票 this mil ng- posit ria 時間 tco ++

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

原題鏈接:https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/

題目:如果你有一個數組,當中的第 i 個元素代表給定的第 i 天的股票價格。

設計一個算法找出最大的利潤。

你能夠完畢多個交易(如,買一和賣一股票 多次)。可是,你不能同一時候進行多個交易(如,你必須在新買入之前賣出)。

思路:能夠理解成求隨意多個二元序列之差 之和 的最大值,當中每對序列之差需為正數。相應的索引要減號之前的大於減號之後的。

比方:[1,2,4,3,5,7,6]這樣一個數組。

能夠這樣計算:

2 - 1 = 1

5 - 4 = 1

7 - 3 = 4

1 + 1 + 4 = 6

也能夠這樣計算:

7 - 1 = 6

6 - 2 = 4

5 - 3 = 2

6 + 4 + 2 = 12

由上的樣例能夠看出,利潤的最大值應該是這樣;依次用後序的最大值減去前面的最小值 之和。分析到這裏,也就能夠利用上一題的做法了,上一題是找到一次交易中利潤最大的,我們要求的是多次交易的最大利潤,能夠轉化為每次都是最大利潤,最後匯總。

詳細做法就是。每次計算完最大利潤之後。將這個最大利潤相應的序列從數組中刪除。再來計算下一次的最大利潤……。

寫的有點復雜了,計算結果應該是錯的,由於並沒有依照時間序列的順序來做,即後一次買入的位置必須在前一次賣出之後。

public class BestTimetoBuyandSellStockII {
	public static void main(String[] args) {
		delete(new int[]{2,1},0);
		int ret = maxProfit(new int[]{1,2,4,3,5,7,6});
		System.out.println(ret);
	}
	public static int maxProfit(int[] prices){
		int len = prices.length;
		if(len <= 1)
			return 0;
		int max = 0;
		T t = max(prices);
		while(true){
			max += t.max;
			if(t.ary.length <= 1)
				break;
			if(t.ary.length == 2){
				if(t.ary[1] < t.ary[0])
					break;
				else
					max += t.ary[1] - t.ary[0];
				break;
			}
			t = max(t.ary);
		}
		return max;
	}
	//每次的最大利潤
	public static T max(int[] prices){
		int len = prices.length;
		if(len <= 1)
			return null;
		int min = prices[0],max = 0,largest = 0;
		for(int i=1;i<len;i++){
			int profit = prices[i] - min;
			if(max < profit){
				max = profit;
				largest = prices[i];
			}
			if(min > prices[i])
				min = prices[i];
		}
		System.out.println("min = " + min + "\tlargest = " + largest + "\tmax = "+ max);
		int[] a = delete(prices,min);
		int[] b = delete(a,largest);
		return new T(max,b);
	} 
	//刪除數組中的某個元素
	public static int[] delete(int[] prices,int price){
		int len = prices.length;
		if(len <= 0 || price <= 0)
			return null;
		int[] ret = new int[len - 1];
		int index = 0;
		for(int i=0;i<len;i++){
			if(prices[i] == price){
				index = i;
				break;
			}
			ret[i] = prices[i];
		}
		for(int i=index;i<ret.length;i++){
			ret[i] = prices[i+1];
		}
		return ret;
	}
	static class T {
		int max;
		int[] ary;
		public T(int max,int[] ary){
			this.max = max;
			this.ary = ary;
		}
	}
}
更簡單的解法是 借鑒了這位網友[1]的思路 ; 從頭到尾掃描prices,假設i比i-1大,那麽price[i] – price[i-1]就能夠計入最後的收益中。這樣掃描一次O(n)就能夠獲得最大收益了。

	public static int maxProfit(int[] prices){
		int len = prices.length;
		if(len <= 1)
			return 0;
		int sum = 0;
		for(int i=1;i<len;i++){
			int profit = prices[i] - prices[i - 1];
			if(profit > 0)
				sum += profit;
		}
		return sum;
	}

[1] reference : http://blog.unieagle.net/2012/12/04/leetcode%E9%A2%98%E7%9B%AE%EF%BC%9Abest-time-to-buy-and-sell-stock-ii/

LeetCode——Best Time to Buy and Sell Stock II