首页 > 代码库 > LeetCode——Best Time to Buy and Sell Stock II

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

原题链接: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

由上的例子可以看出,利润的最大值应该是这样;依次用后序的最大值减去前面的最小值 之和。分析到这里,也就可以利用上一题的做法了,上一题是找到一次交易中利润最大的,我们要求的是多次交易的最大利润,可以转化为每次都是最大利润,最后汇总。具体做法就是,每次计算完最大利润之后,将这个最大利润对应的序列从数组中删除。再来计算下一次的最大利润……。写的有点复杂了,计算结果应该是对的,但是return null那里没有通过。

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/