leetcode之Best Time to Buy and Sell Stock && II && III

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.

上題是求最大利潤,利用動態規劃的思想,在遍歷的過程中只需保留之前的最小值和最大利潤兩個值,如果當前節點減去之前的最小值的差比最大利潤大,則更新最大利潤,如果當前節點比之前的最小值小,則更新最小值,便利完成後即得到最大利潤。

int maxProfit(vector<int> &prices) {
		if(prices.size() <= 1)
			return 0;
		int min = prices[0];
		int maxP = 0;
		for(int i = 1; i < prices.size(); i++){
			if(prices[i] - min > maxP)
				maxP = prices[i] - min;
			if(prices[i] < min)
				min = prices[i];
		}
		return maxP;
	}
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,2,4這三個數,交易兩次的最大利潤和交易一次的最大利潤是相同的,所以,我們在編程實現時只需將當前節點與其前一個節點進行比較,如果差值大於零,則可成交一次,同樣是遍歷一次後得到最大利潤,時間複雜度爲O(n)。

int maxProfit(vector<int> &prices) {
		if(prices.size() <= 1)
			return 0;
		int maxP = 0;
		for(int i = 1; i < prices.size(); i++){
			if(prices[i] > prices[i - 1])
				maxP += prices[i] - prices[i - 1];
		}
		return maxP;
	}

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

可能是發現了在次數沒有限制的情況下並沒有增加多少難度,所以此題限制最多交易兩次,此時可以採用分而治之的思想,針對每個節點,將其分爲節點左邊的最大利潤和節點右邊的最大利潤,在掃描一遍的情況下即可得出最大利潤,此時,求左邊節點和右邊節點最大利潤的問題變成第一題的一次交易的最大利潤問題,所以總的時間複雜度是O(n*n),在leetcode上提交時出現超時錯誤。

int maxProfit(vector<int> &prices) {
		if(prices.size() <= 1)
			return 0;
		int maxLeft = 0,maxRight = 0,max = 0;
		for(int i = 2; i < prices.size(); i++){
			maxLeft = maxProfit(prices,0,i);
			maxRight = maxProfit(prices,i,prices.size() - 1);
			if(maxLeft + maxRight > max)
				max = maxLeft + maxRight;
		}
		return max;
	}
	int maxProfit(vector<int>prices,int left,int right){
		if(left >= right)
			return 0;
		int min = prices[left];
		int maxP = 0;
		for(int i = left + 1; i <= right; i++){
			if(prices[i] - min > maxP)
				maxP = prices[i] - min;
			if(prices[i] < min)
				min = prices[i];
		}
		return maxP;
	}
上述求解思路是沒問題的,接下來就是對其進行優化的問題,仍採用動態規劃的思想,此時可以借鑑騰訊2012年的校招題的做法:http://blog.csdn.net/momentforver/article/details/23266391,但不同的是,此題只需利用一個數組保存節點左邊的最大利潤,而因爲在求解節點右邊的最大利潤後即可得出最大利潤,所以沒有必要對節點右邊的最大利潤進行保存。此時空間複雜度爲O(n),需要掃描兩遍數組,所以其時間複雜度爲O(n)。

int maxProfit(vector<int> &prices) {
		int len = prices.size();
		if(len <= 1)
			return 0;
		vector<int>vLeft(len,0);		
		int maxP = 0,min = prices[0],max = prices[len - 1],maxProfit = 0;
		for(int i = 1; i < len; i++)   //求當前節點左邊的最大利潤
		{
			if(prices[i] - min > maxP){
				maxP = prices[i] - min;				
			}	
			if(prices[i] < min)
				min = prices[i];
			vLeft[i] = maxP;
		}
		maxP = 0;
		for(int i = len - 2; i >= 0; i--){   //求當前節點右邊的最大利潤,同時計算左右最大利潤
			if(max - prices[i] > maxP)
				maxP = max - prices[i];			
			if(prices[i] > max)
				max = prices[i];			
			if(vLeft[i] + maxP >  maxProfit)
				maxProfit = vLeft[i] +maxP;
		}
		return maxProfit;
	}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章