您的位置:首页 > 编程语言 > C语言/C++

第一周:( LeetCode ) Best Time to Buy and Sell Stock I II III(c++)

2017-02-24 13:43 746 查看
写在前面:

最近做项目一直用python,有三四年没碰c++了。这学期学算法,由于期末考试要用c或者c++进行机考,老师布置作业每周至少做一道leetcode的题,并写题解发表在csdn上,这是第一次。

本来只打算做一道easy题恢复下感觉,没想到刚好做了I 之后看 到又有II和III,所以就挑战了下自我。

I 、II是easy,大概各花了我半小时;III是hard,刚开始思路还是有点难想的,容易想到的思路超时了,大概花了我一个晚上才AC。

废话不多说,直接看题!

Best Time to Buy and Sell Stock I

原题:Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

思路:买卖股票肯定是在最低的点买入,最高的点卖出,赚得最多!但是前提是最高的点出现在最低的点后面,所以这里有个时间出现先后的问题,不是直接拿最大值减去最小值。以下的思路是遍历prices[i],用min表示到目前为止(遍历到prices[i-1]时)出现的最小的值,用maxpro表示到目前为止(遍历到prices[i-1]时)的最大收益。如果prices[i]比min还小,就更新min,这时不用更新maxpro;如果prices[i]比min大,再判断在min买入并在此点(prices[i])卖出的值和之前的maxpro的大小关系,取其大者为新的maxpro。这里其实用到动态规划的思想,其递归表达式为:maxpro(i)=max(maxpro(i-1),prices[i]-min)。该解法时间复杂度为:o(n)。

代码如下:

class Solution {
public:
int maxProfit(vector<int>& prices) {
int min,tempmax,maxpro;
maxpro=0;
for(int i=0;i<prices.size();i++){
if(i==0){
min=prices[i];
}
if(prices[i]<min){
min=prices[i];
}else{
tempmax=prices[i]-min;
if(tempmax>maxpro){
maxpro=tempmax;
}
}
}
return maxpro;
}
};


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

思路:题意就是在 I 的基础上,允许进行多次买卖,以达到收益的最大化。经过仔细思考,此问题也是o(n)复杂度的问题,关键在于如何判断在某个点应该卖出股票、买入股票还是不进行任何操作。如何进行判断?关键在于prices[i+1]和prices[i]的关系,如果prices[i+1]>prices[i],而且此时手上持有股票,那么此时(prices[i])不应该卖出,因为后面(prices[i+1])还可以卖出更好的价钱,所以不进行任何操作;如果此时手上没有股票,那要果断买入,因为后面(prices[i+1])即将可以收益。如果prices[i+1]<=prices[i],如果此时手上有股票,那必须果断卖出,因为下一阶段(prices[i+1])就卖不出这么好的价钱了;如果此时手上没股票,那不要着急,下一阶段(prices[i+1])还可以买到更便宜的,所以不用进行操作。解决了以上核心问题,那么问题就迎刃而解了。以下代码中用flag来表示某一刻手上是否有股票,还要注意一些界限的处理问题。

代码如下:

class Solution {
public:
int maxProfit(vector<int>& prices) {
int flag=0;
int profit=0;
int buy,sell=0;
if(prices.size()==0){
return profit;
}
for(int i=0;i<(prices.size()-1);i++){
if(prices[i]<prices[i+1]){
if(!flag){
flag=1;
buy=prices[i];
}
}else{
if(flag){
flag=0;
sell=prices[i];
profit+=(sell-buy);
}
}
}
if(flag && (prices[prices.size()-1]>buy)){
profit+=(prices[prices.size()-1]-buy);
}
return profit;
}
};


Best Time to Buy and Sell Stock III

原题: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.

思路:在I 和 II的基础上,此题限定只能进行1-2次的买卖。刚开始有点偷懒,直接进行分类,分成一次和两次买卖这两种情况,一次买卖直接用第一题的结果,两次买卖也就是把prices直接分成[0,1,…,i]和[i+1,i+2,…,n-1]两段,每一段直接用第一题的函数求出单次买卖最大利润,然后再将两次结果相加取最大值,复杂度是o(n^2),结果果然超时!后面仔细分析,分成两段的思路虽然是对的,但直接用第一题的函数重复进行了很多次计算。在第一题的基础上,如果在遍历的过程中,用一个maxpro_of_first[i]的数组保存从前往后遍历到某个位置前面[0,1,…,i]这个区间进行一次买卖的收益最大值;再用maxpro_of_second[i]从后往前遍历[i+1,i+2,…,n-1]区间进行一次买卖的收益最大值。再将两者相加取最大即可得到结果,这样的复杂度仅为o(3n),也即o(n)。举例:prices=[7,1,5,3,6,4],从前往后遍历maxpro_of_first的结果为[0,0,4,4,5,5],从后往前遍历maxpro_of_second的结果为[5,5,3,3,0,0],将maxpro_of_first[i]和maxpro_of_second[i]相加得到[5,5,7,7,5,5],所以结果为7。

代码如下:

class Solution {
public:
int maxProfit(vector<int>& prices){
const int len=prices.size();
if(len==0){
return 0;
}
int maxpro_of_first[len],maxpro_of_second[len]={0};
int min,maxpro,res,max;
maxpro=0;
for(int i=0;i<len;i++){
if(i==0){
min=prices[i];
}
if(prices[i]<min){
min=prices[i];
}else{
maxpro_of_first[i]=prices[i]-min;
if(maxpro_of_first[i]>maxpro){
maxpro=maxpro_of_first[i];
}
}
maxpro_of_first[i]=maxpro;
}
maxpro=0;
for(int i=len-1;i>=0;i--){
if(i==len-1){
max=prices[i];
}
if(prices[i]>max){
max=prices[i];
}else{
maxpro_of_second[i]=max-prices[i];

aba3
if(maxpro_of_second[i]>maxpro){
maxpro=maxpro_of_second[i];
}
}
maxpro_of_second[i]=maxpro;
}
res=0;
for(int i=0;i<len;i++){
if((maxpro_of_first[i]+maxpro_of_second[i])>res){
res=maxpro_of_first[i]+maxpro_of_second[i];
}
}
return res;
}
};


以上三题基本上都和动态规划息息相关,动态规划的题思路一般比较难想,递推关系常常很难找。算法课也还没讲到动态规划的章节,所以笔者的理解仍然十分有限,需要后续加强。由于笔者近几年接触c++比较少,很多语法都已经忘记,也没有花专门的时间去美化代码和写注释,代码写得很挫,望批评指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息