在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于 2 ),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用时间复杂度低的方法实现。
给定价格序列 prices 及它的长度 n ,请返回最大收益。
数据范围: ,
在股市的交易日中,假设最多可进行两次买卖(即买和卖的次数均小于等于 2 ),规则是必须一笔成交后进行另一笔(即买-卖-买-卖的顺序进行)。给出一天中的股票变化序列,请写一个程序计算一天可以获得的最大收益。请采用时间复杂度低的方法实现。
[10,22,5,75,65,80],6
87
import java.util.*; public class Stock { public int maxProfit(int[] prices, int n) { // write code here // 动态规划(易于理解版本) // 0: 第一次买入 // 1: 第一次卖出 // 2: 第二次买入 // 3: 第二次卖出 int[][] dp = new int[n][4]; // 第一个元素,长度为1,只能执行买入操作。 dp[0][0] = -prices[0]; dp[0][1] = -prices[0]; dp[0][2] = -prices[0]; dp[0][3] = -prices[0]; for (int i = 1; i < n; i++) { // 在 当前不买入 和 当前买入 取最大 dp[i][0] = Math.max(dp[i - 1][0], -prices[i]); // 在 当前不卖出 和 当前卖出 取最大 dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]); // 在 当前不买入 和 当前买入 取最大 dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] - prices[i]); // 在 当前不卖出 和 当前卖出 取最大 dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] + prices[i]); } // 最大收益应该大于等于0,因为可以什么也不买不卖 return Math.max( 0, Math.max(dp[n - 1][1], dp[n - 1][3]) ); } }
import java.util.*; public class Stock { public int maxProfit(int[] prices, int n) { int firstBuy = Integer.MIN_VALUE,firstSell = 0; int secondBuy = Integer.MIN_VALUE,secondSell = 0; for (int price : prices) { firstBuy = Math.max(firstBuy, -price); firstSell = Math.max(firstSell, firstBuy + price); secondBuy = Math.max(secondBuy, firstSell - price); secondSell = Math.max(secondSell, secondBuy+price); /*firstBuy更新则firstSell不更新,差值大才更新 1.firstBuy比过去买的价格高,无论何时差值一定比过去小,必不买 2.firstBuy比过去买的价格低,firstBuy这轮跟踪,firstSell这轮不变(同secondBuy) */ /*secondBuy更新则secondSell不更新,差值大才更新 1.firstSell更新引起的(firstBuy保持不变,secondBuy=max(secondBuy,firstBuy)), firstBuy一定是最低价格,故secondBuy=firstBuy,比较max(以前secondSell,现在firstSell) 2.price比过去的价格低,secondBuy这轮跟踪,secondSell这轮不变 这里price低只针对的是secondBuy的过去价格,secondBuy与firstBuy起点不同, firstBuy的价格一定是最低价,最低价 < 这里price < secondBuy的过去价格 */ } return secondSell; } }
/** 以第i天为分界线, 计算 [0, i-1]和[i, n-1]的最大收益,取和最大的 */ import java.util.*; public class Stock { public int maxProfit(int[] prices, int n) { // write code here if(n <= 4) return 0; int res = 0; for(int i = 2; i < n; i++){ res = Math.max(res, maxProfit(prices, 0, i-1) + maxProfit(prices, i, n-1)); } return res; } public int maxProfit(int[] prices, int start, int end){ if(start >= end) return 0; int left = start, right = start+1; int res = Math.max(prices[right] - prices[left], 0); while(right <= end){ if(prices[right] > prices[left]){ res = Math.max(res, prices[right] - prices[left]); right++; }else{ left = right; right++; } } return res; } }
import java.util.*; public class Stock { public int helper(int[] prices, int n, int x, int y) { if(x >= y) return 0; int[] pre = new int[n]; int[] pos = new int[n]; pre[x] = prices[x]; pos[y] = prices[y]; for(int i = x+1; i <= y; i++) pre[i] = Math.min(pre[i-1], prices[i]); for(int i=y-1; i >= x; i--) pos[i] = Math.max(pos[i+1], prices[i]); int res = 0; for(int i=x; i <= y; i++) { res = Math.max(res, pos[i] - pre[i]); } return res; } public int maxProfit(int[] prices, int n) { int res = 0; for(int i=0; i < n; i++) { int t = helper(prices, n, 0, i); t += helper(prices, n, i+1, n-1); res = Math.max(res, t); } return res; } }
import java.util.*; public class Stock { public static int maxProfit(int[] prices, int n) { int[] leftProfit = new int[prices.length]; int[] rightProfit = new int[prices.length]; int minValue = prices[0]; int maxProfit = 0; for (int i = 1; i < prices.length; ++i) { if (prices[i] - minValue > leftProfit[i - 1]) { leftProfit[i] = prices[i] - minValue; } else { leftProfit[i] = leftProfit[i - 1]; } if (prices[i] < minValue) { minValue = prices[i]; } } int maxValue = prices[prices.length - 1]; for (int i = prices.length - 2; i >= 0; --i) { if (maxValue - prices[i] > rightProfit[i + 1]) { rightProfit[i] = maxValue - prices[i]; } else { rightProfit[i] = rightProfit[i + 1]; } if (prices[i] > maxValue) { maxValue = prices[i]; } } for (int i = 0; i < prices.length - 1; ++i) { if (leftProfit[i] + rightProfit[i + 1] > maxProfit) maxProfit = leftProfit[i] + rightProfit[i + 1]; } if (leftProfit[leftProfit.length - 1] > maxProfit) { maxProfit = leftProfit[leftProfit.length - 1]; } if (rightProfit[0] > maxProfit) { maxProfit = rightProfit[rightProfit.length - 1]; } return maxProfit; } public static void main(String[] args) { int[] prices = { 10, 22, 5, 75, 65, 80 }; maxProfit(prices, prices.length); } }
import java.util.*; public class Stock { public int maxProfit(int[] prices, int n) { int firstBuy = Integer.MIN_VALUE, firstSell = 0; int secondBuy = Integer.MIN_VALUE, secondSell = 0; for (int curPrice : prices) { firstBuy = Math.max(firstBuy, -curPrice); firstSell = Math.max(firstSell, firstBuy + curPrice); secondBuy = Math.max(secondBuy,firstSell - curPrice); secondSell = Math.max(secondSell, secondBuy + curPrice); } return secondSell; } }
import java.util.*; public class Stock { public int maxProfit(int[] prices, int n) { int dp[] = new int[n]; int max = 0; for (int i = 0; i < dp.length; i ++ ) dp[i] = getProfit(prices, 0, i) + getProfit(prices, i, n - 1); for (int i = 0; i < dp.length; i ++ ) max = max > dp[i] ? max : dp[i]; return max; } public static int getProfit(int[] prices, int start, int end) { int profit = 0; for (int i = start; i <= end; i ++ ) for (int j = i + 1; j <= end; j ++ ) profit = profit > prices[j] - prices[i] ? profit : prices[j] - prices[i]; return profit; } }
import java.util.*; //已通过测试,发现好多人都不喜欢写注释,喜欢直接粘代码, public class Stock { //简单说一下我的做题思路, //其实我的原始思路是用二分法做,先把数组从中间分开, //然后在两部分中分别找最大差值,然后保存最大差值进行相加 //完事之后,将中间的指针,也就是进行二分的指针向右移或者向左移 //又划分成了两部分,依次找最大差值, //直到最后两个差值之和为最大值,返回最大值。 public int maxProfit(int[] prices, int n) { int temp1 = 0,temp2 = 0 , temp3 = 0, l = 0; //既然从中间划分两部分,之后又要在往前划分和往后划分, //所以直接一开始就从最前面开始划分,将数组划分两部分 while(l<n){ //l变量用来划分数组 //第一个for循环寻找的最大差值,仅限于l变量之前。 for(int i = 0 ; i < l+1 ; i++){ for(int j = i+1 ; j < l+1 ; j++){ if(prices[j]-prices[i]>temp1){ temp1 = prices[j]-prices[i]; } } } //第二个for循环寻找的最大差值,仅限于l变量之后。 for(int i = l+1 ; i < n ; i++){ for(int j = i+1 ; j < n ; j++){ if(prices[j]-prices[i]>temp2){ temp2 = prices[j]-prices[i]; } } } //判断两个变量之和是否是最大差值 if(temp2+temp1>temp3){ temp3 = temp2+temp1 ; } //此处一定要将两个部分的最大差值重新置0; //否则结果会出错。因为它里面存有之前的最大差值 //如果不重置,那么最后在判断的时候会重复计算。 temp2 = 0 ; temp1 = 0; l++; } return temp3; } }
import java.util.*; public class Stock { public int[] getMax(int[] dis, int n) { int[] dp = new int[n]; int max = Integer.MIN_VALUE; int current = 0; for (int i = 0; i < dis.length; ++i) { current += dis[i]; current = Math.max(current, dis[i]); max = Math.max(current, max); dp[i] = max; } return dp; } public int[] getMin(int[] dis, int n) { int[] dp = new int[n]; int min = Integer.MAX_VALUE; int current = 0; for (int i = dis.length - 1; i >= 0; --i) { current += dis[i]; current = Math.min(current, dis[i]); min = Math.min(current, min); dp[i] = min; } return dp; } public int maxProfit(int[] prices, int n) { // write code here int[] dis = new int[prices.length]; int[] dis2 = new int[prices.length]; for (int i = 1; i < dis.length; ++i) { dis[i] = prices[i] - prices[i - 1]; } for (int i = dis.length - 2; i >= 0; --i) { dis2[i] = prices[i] - prices[i + 1]; } int[] max = getMax(dis, n); int[] min = getMin(dis2, n); int result = Integer.MIN_VALUE; for (int i = 0; i < max.length; ++i) { result = Math.max(result, max[i] - min[i]); } return result; } }