假设你有一个数组,其中第i个元素是某只股票在第i天的价格。
设计一个算法来求最大的利润。你最多可以进行两次交易。
注意:
你不能同时进行多个交易(即,你必须在再次购买之前出售之前买的股票)。
设计一个算法来求最大的利润。你最多可以进行两次交易。
注意:
你不能同时进行多个交易(即,你必须在再次购买之前出售之前买的股票)。
class Solution { /** * 延续之前的转移方程,假设第i天持有为1,空仓为0 * 不一样的是因为限定交易次数,还要加一个参数k * 第i天第k次交易的持有收益是f(i,k,1), 空仓收益是f(i,k,0) * 有: * f(i,k,0) = max(f(i-1,k,0), f(i-1,k,1)+prices[i]) * f(i,k,1) = max(f(i-1,k,1), f(i-1,k-1,0)-prices[i]) * 这样顺带下一题也搞定了 */ public int maxProfit(int[] prices) { if(prices.length<2) return 0; int k1j0 = 0, k1j1 = -prices[0], k2j0 = 0, k2j1 = -prices[0]; for(int i=1; i<prices.length; i++){ k2j0 = Math.max(k2j0, k2j1+prices[i]); k2j1 = Math.max(k2j1, k1j0-prices[i]); k1j0 = Math.max(k1j0, k1j1+prices[i]); k1j1 = Math.max(k1j1, 0-prices[i]); } return k2j0; } }
//结合分治的思维并结合在线处理的算法去求得子区间最大利润:
public class Solution {
public int maxProfit(int[] prices) {
int maxprofit = 0; if (prices.length < 2) { //区间长度小于2返回0. return 0; } if (prices.length == 2) { //区间长度为2 return Math.max(maxprofit, prices[1] - prices[0]); } //区间长度大于等于3,采取分治的思想,分为两个子区间。分别求解子区间内的最大利润 for (int i = 1; i <= prices.length - 2; i++) { maxprofit = Math.max(maxprofit,(maxProfitcore(prices, 0, i) + maxProfitcore(prices, i, prices.length - 1))); } return maxprofit; } //在线处理求该区间的最大利润 public int maxProfitcore(int[] prices, int left, int right) { int profit = 0; int i = left; for (int j = left + 1; j <= right; j++) { if (prices[j] - prices[i] > 0) { int temp = prices[j] - prices[i]; profit = Math.max(temp, profit); }else { i = j; } } return profit; } }
public class Solution { public int maxProfit(int[] prices) { int buy1 = Integer.MIN_VALUE, sell1 = 0, buy2 = Integer.MIN_VALUE, sell2 = 0; for(int i = 0; i < prices.length; i++) { buy1 = Math.max(buy1, -prices[i]); sell1 = Math.max(sell1, buy1 + prices[i]); buy2 = Math.max(buy2, sell1 - prices[i]); sell2 = Math.max(sell2, buy2 + prices[i]); } return sell2; } }
public static int maxProfit(int[] prices) { if (prices == null || prices.length <= 1) return 0; int len = prices.length; int[] leftMaxProfit = new int[len]; int[] rightMaxProfit = new int[len]; // left int leftMinIndex = 0; for (int i = 0; i < len; ++i) { if (i == 0) { leftMaxProfit[i] = 0; leftMinIndex = 0; continue; } if (prices[i] - prices[i - 1] > 0) { leftMaxProfit[i] = Math.max(prices[i] - prices[leftMinIndex], leftMaxProfit[i - 1]); } else { if (prices[i] < prices[leftMinIndex]) { leftMinIndex = i; leftMaxProfit[i] = leftMaxProfit[i - 1]; } else { leftMaxProfit[i] = leftMaxProfit[i - 1]; } } } // right int rightMaxIndex = 0; for (int j = len - 1; j >= 0; --j) { if (j == len - 1) { rightMaxIndex = j; rightMaxProfit[j] = 0; continue; } if (prices[j + 1] - prices[j] > 0) { rightMaxProfit[j] = Math.max(prices[rightMaxIndex] - prices[j], rightMaxProfit[j + 1]); } else { if (prices[j] > prices[rightMaxIndex]) { rightMaxIndex = j; rightMaxProfit[j] = rightMaxProfit[j + 1]; } else { rightMaxProfit[j] = rightMaxProfit[j + 1]; } } } int maxProfit = 0; int temp = 0; // split for (int i = 0; i < len; ++i) { temp = leftMaxProfit[i] + rightMaxProfit[i]; if (temp > maxProfit) maxProfit = temp; } return maxProfit; }
/** * 分别计算出i之前和之后的最大利润pre[i],post[i] * 再以i为分割求出两次交易的最大利润(在i处可能卖出再买入,相当于就一次交易) * 空间换时间,时间复杂度O(n),空间复杂度O(n) * @param prices * @return */ public int maxProfit(int[] prices) { if(prices==null||prices.length<2) return 0; int[]pre=new int[prices.length]; int []post=new int[prices.length]; int min=prices[0]; for(int i=1;i<prices.length;i++){ min=Math.min(min,prices[i]); pre[i]=Math.max(pre[i-1],prices[i]-min); } int max=prices[prices.length-1]; for(int i=prices.length-2;i>=0;i--){ max=Math.max(max,prices[i]); post[i]=Math.max(post[i+1],max-prices[i]); } int maxProfit=0; for(int i=0;i<prices.length;i++){ maxProfit=Math.max(maxProfit,pre[i]+post[i]); } return maxProfit; }
import java.util.*; public class Solution { public int maxProfit(int[] prices) { int fb=Integer.MIN_VALUE,sb=Integer.MIN_VALUE,fs=0,ss=0; for(int i:prices){ fb=Math.max(fb,-i); fs=Math.max(fs,fb+i); sb=Math.max(sb,fs-i); ss=Math.max(ss,sb+i); } return ss; } }
public class Solution { public int maxProfit(int[] prices) { return Math.max(once(0, prices.length - 1, prices), twice(prices)); } public int once(int start, int end, int[] prices) { int max = 0; for (int i = start; i <= end; i ++) { int sell = 0; for (int j = i; j <= end; j ++) { sell = sell > prices[j] ? sell : prices[j]; } max = max > sell - prices[i] ? max : sell - prices[i]; } return max; } public int twice(int[] prices) { int max = 0; for (int i = 0; i < prices.length; i ++) { int sell = once(0, i, prices) + once(i, prices.length - 1, prices); max = max > sell ? max : sell; } return max; } }
public class Solution { public int maxProfit(int[] prices) { int hold1 = Integer.MIN_VALUE, hold2 = Integer.MIN_VALUE; int release1 = 0, release2 = 0; for(int i:prices){ // Assume we only have 0 money at first release2 = Math.max(release2, hold2+i); // The maximum if we've just sold 2nd stock so far. hold2 = Math.max(hold2, release1-i); // The maximum if we've just buy 2nd stock so far. release1 = Math.max(release1, hold1+i); // The maximum if we've just sold 1nd stock so far. hold1 = Math.max(hold1, -i); // The maximum if we've just buy 1st stock so far. } return release2; ///Since release1 is initiated as 0, so release2 will always higher than release1. } }
public int maxProfit(int[] prices) { int result = 0; if(prices == null || prices.length < 2){ return 0; } if(prices.length == 2){ return prices[1] - prices[0] > 0 ? prices[1] - prices[0] : 0; } if(prices.length == 3){ result = prices[2] - prices[0] > result ? prices[2] - prices[0] : result; result = prices[1] - prices[0] > result ? prices[1] - prices[0] : result; result = prices[2] - prices[1] > result ? prices[2] - prices[1] : result; return result; } int[] dp = new int[prices.length]; int maxPrice = prices[prices.length - 1]; for(int i = prices.length - 2; i >= 0; --i){ int temp = maxPrice - prices[i]; dp[i] = temp > dp[i + 1] ? temp : dp[i + 1]; maxPrice = maxPrice > prices[i] ? maxPrice : prices[i]; result = result > dp[i] ? result : dp[i]; } int minPrice = prices[0]; int maxProfit = 0; for(int i = 1; i < prices.length - 1; ++i){ int temp = prices[i] - minPrice; maxProfit = maxProfit > temp ? maxProfit : temp; minPrice = minPrice < prices[i] ? minPrice : prices[i]; result = result > maxProfit ? result : maxProfit; result = result > maxProfit + dp[i + 1] ? result : maxProfit + dp[i + 1]; } return result; }