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

由上的例子可以看出,利润的最大值应该是这样;依次用后序的最大值减去前面的最小值 之和。分析到这里,也就可以利用上一题的做法了,上一题是找到一次交易中利润最大的,我们要求的是多次交易的最大利润,可以转化为每次都是最大利润,最后汇总。具体做法就是,每次计算完最大利润之后,将这个最大利润对应的序列从数组中删除。再来计算下一次的最大利润……。写的有点复杂了,计算结果应该是错的,因为并没有按照时间序列的顺序来做,即后一次买入的位置必须在前一次卖出之后!

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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值