博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【leetcode】Best Time to Buy and Sell 3 (hard) 自己做出来了 但别人的更好
阅读量:6500 次
发布时间:2019-06-24

本文共 5781 字,大约阅读时间需要 19 分钟。

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

 

思路:

方案一:两次交易,得到最大收入。 设原本有length个数据,用n把数据分为[0 ~ n-1] 和 [n ~ length-1]两个部分,分别求最大收入,再加起来。结果超时了。

方案二:设数据是                        0  2  1  4  2  4  7 

求后一个数字和前一个数字的差值:   2 -1  3  -2  2  3

把连续符合相同的数累加                 2 -1  3  -2   5

这样处理后,假设有m个数据, 用n把数据分为[0 ~ n-1] 和 [n ~ m-1]两个部分, 分别求两个部分的最大连续子段和。

由于经过预处理,数据变少了很多,所以就AC了。

int maxProfit3(vector
&prices) { if(prices.size() < 2) { return 0; } //第一步:把prices中的数 两两间的差值算出来 把差值符号相同的加在一起 vector
dealPrices; vector
::iterator it; int last = prices[0]; int current; int sumNum = 0; for(it = prices.begin() + 1; it < prices.end(); it++) { current = *it; if((current - last >= 0 && sumNum >= 0) || (current - last <= 0 && sumNum <= 0)) { sumNum += current - last; } else { dealPrices.push_back(sumNum); sumNum = current - last; } last = current; } if(sumNum != 0) { dealPrices.push_back(sumNum); } //第二步 if(dealPrices.size() == 1) { return dealPrices[0] > 0 ? dealPrices[0] : 0; } else { int maxprofit = 0; for(int n = 1; n < dealPrices.size(); n++) { //求前半段最大连续子段和 int maxSum1 = 0; int maxSum2 = 0; int curSum = 0; for(int i = 0; i < n; i++) { curSum = (curSum > 0) ? curSum + dealPrices[i] : dealPrices[i]; maxSum1 = (curSum > maxSum1) ? curSum : maxSum1; } //求后半段最大连续子段和 curSum = 0; for(int i = n; i < dealPrices.size(); i++) { curSum = (curSum > 0) ? curSum + dealPrices[i] : dealPrices[i]; maxSum2 = (curSum > maxSum2) ? curSum : maxSum2; } if(maxSum1 + maxSum2 > maxprofit) { maxprofit = maxSum1 + maxSum2; } } return maxprofit; }

 

虽然我的AC了,但实际上还是个O(N^2)的算法,来看看大神们的O(N)代码。

第一种:

用两个数组left[],right[].

left记录当前值减去它前面的最小值的结果

right记录 当前值后面的最大值减去当前值的结果

把 left[i]+right[i+1] 针对所有的i遍历一遍 得到最大的值就是答案

public class Solution {    public int maxProfit(int[] prices) {        if (prices.length < 2) return 0;//one of zero days, cannot sell        // break the problem in to subproblems, what is the max profit if i decide to buy and sell one stock on or before day i        // and the other stock after day i        int[] left = new int[prices.length];//store the max profit so far for day [0,i] for i from 0 to n        int[] right = new int[prices.length];//store the max profit so far for the days [i,n] for i from 0 to n        int minl,maxprofit,maxr,profit;        maxprofit = 0;//lower bound on profit        minl = Integer.MAX_VALUE;//minimum price so far for populating left array        for(int i = 0; i < left.length; i++){            if (prices[i] < minl) minl = prices[i];//check if this price is the minimum price so far            profit = prices[i] - minl;//get the profit of selling at current price having bought at min price so far            if (profit > maxprofit) maxprofit = profit;//if the profit is greater than the profit so far, update the max profit            left[i] = maxprofit;        }        maxprofit = 0;//reset maxprofit to its lower bound        maxr = Integer.MIN_VALUE;//maximum price so far for populating the right array        //same line of reasoning as the above        for(int i = left.length - 1; i >= 0; i--){            if (prices[i] > maxr) maxr = prices[i];            profit = maxr - prices[i];            if (profit > maxprofit) maxprofit = profit;            right[i] = maxprofit;        }        //get the best by combining the subproblems as described above        int best = 0;        for(int i = 0; i < prices.length - 1; i++){            if (left[i] + right[i+1] > best) best = left[i] + right[i+1];        }        best = best > maxprofit ? best : maxprofit;        // in total 3 passes required and 2 extra arrays of size n        return best;    }}

 

第二种:更厉害,泛化到了k次交易的情况 而且代码特别短

class Solution {public:    int maxProfit(vector
&prices) { // f[k, ii] represents the max profit up until prices[ii] (Note: NOT ending with prices[ii]) using at most k transactions. // f[k, ii] = max(f[k, ii-1], prices[ii] - prices[jj] + f[k-1, jj]) { jj in range of [0, ii-1] } // = max(f[k, ii-1], prices[ii] + max(f[k-1, jj] - prices[jj])) // f[0, ii] = 0; 0 times transation makes 0 profit // f[k, 0] = 0; if there is only one price data point you can't make any money no matter how many times you can trade if (prices.size() <= 1) return 0; else { int K = 2; // number of max transation allowed int maxProf = 0; vector
> f(K+1, vector
(prices.size(), 0)); for (int kk = 1; kk <= K; kk++) { int tmpMax = f[kk-1][0] - prices[0]; for (int ii = 1; ii < prices.size(); ii++) { f[kk][ii] = max(f[kk][ii-1], prices[ii] + tmpMax); tmpMax = max(tmpMax, f[kk-1][ii] - prices[ii]); maxProf = max(f[kk][ii], maxProf); } } return maxProf; } }};

 

转载地址:http://gyvyo.baihongyu.com/

你可能感兴趣的文章
linux不能访问80端口,lunux开放80端口(本地访问不了linux文件可能是这个原因)...
查看>>
linux查看与开启sshd服务,[转载]linux查看与开启sshd服务
查看>>
android单位转换小程序,微信小程序中rpx与rem单位转换
查看>>
html绝对定位重叠,HTML_firefox下绝对定位元素重叠造成不可点击问题,重构地图网站过程中碰到的,f - phpStudy...
查看>>
ps切图教程 android,PS前端切图完整教程
查看>>
html显示服务器状态,显示服务器时间并一直显示(html代码)
查看>>
在线html代码优化,网站seo优化html代码方法
查看>>
HTML如何把输入框变成必填值,required输入框为必填项
查看>>
在html中哪一个不是链接的目标属性,HTML试题
查看>>
android otg 挂载流程,android USB OTG功能如何打开及实现
查看>>
html属性board,pin_board.html
查看>>
html定位有几种,POSITION定位有哪几种?各有什么特点?
查看>>
苹果平板可以用html么,如何将ipad苹果平板电脑中的safari浏览器禁用
查看>>
背锅侠逆袭之路
查看>>
移动互联企业级应用三大场景
查看>>
vmware的APD和PDL详细解析
查看>>
理解:思科设备上的网络地址翻译功能(NAT)功能
查看>>
演示:使用协议分析器取证IPv6的报文结构
查看>>
oracle 11gr2 rac中的4种IP解说
查看>>
为什么你找不到工作?
查看>>