您的位置:首页 > 其它

Best Time to Buy and Sell Stock

2016-05-24 19:53 232 查看

Best Time to Buy and Sell Stock

问题描述

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

例如有一个数组,数组中的第i个原色表示某支股票在第i天的价格,求最大利润。

约束1

约束条件

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.

如果最多只允许完成一次交易(例如:买一次和卖一次股票),设计一个求最大利润算法。

解题思路1

prices(i)表示第i天股票的价格,profits(i)表示第i天卖出的最大利润,则:

profits(i)=prices(i)−minprices(j)(j≤i)则最大利润为max{profits(i)}。 算法的时间复杂度为o(n),空间复杂度为o(1)

代码(C++)1

class Solution {
public:
int maxProfit(vector<int> &prices) {
int profit = 0;
if(prices.size()>=2){
int min = prices[0];
for(int i =1;i<prices.size();i++){
min = min > prices[i] ?  prices[i] : min;
profit = profit > prices[i] - min ? profit :  prices[i] - min;
}
}
return profit;
}
};


思路2

如果使用o(n)的辅助空间,分别计算出第i天相对于第i-1天的利润,则此问题可以转换为求连续子序列最大和。此时算法复杂度也是o(n),但空间复杂度为o(n)。

代码(C++)2

class Solution {
public:
int maxProfit(vector<int> &prices) {
int profit = 0;
if(prices.size()>=2){
//计算当日相对于前一日的利润
vector<int> profits(prices.size(),0);
for(int i =1;i<prices.size();i++){
profits[i] = prices[i] - prices[i-1];
}
//计算连续子序列最大和
for(int i =1;i<prices.size();i++){
profits[i] = profits[i-1] + profits[i] > profits[i] ?profits[i-1] + profits[i] : profits[i] ;
profit = profit > profits[i]?profit:profits[i];
}
}
return profit;
}
};


约束2

约束条件

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

如果可以完成任意多次交易(多次买卖股票),但是多次交易不能同时完成(下一次买股票之前先把股票卖出)。

解题思路

采用贪心算法,只要当日价格高于前一日价格,则前一日买入,当日卖出。实际上,如果连续多日股票价格上涨,相当于在一个升区间内,价格最低时买入,价格最高时卖出(即相当于一次交易)。此时算法复杂度也是o(n),但空间复杂度为o(1)。

代码(C++)

class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0;
for(int i =1;i<prices.size();i++){
//如果当日价格小于前日一价格,收益为0
profit += (prices[i] > prices[i-1] ? prices[i]- prices[i-1] : 0);
}
return profit;
}
};


约束3

约束条件

Design an algorithm to find the maximum profit. You may complete at most two transactions.

若最多交易两次,求最大利润。

解题思路

最多交易两次时,可从数组任意位置分成两个数组。每个数组可以按照交易一次求最大值,两者之和即为在此位置分开时最多交易两次时的最大利润,记为profits(i)。只交易一次时最大利润即为profit,则最多交易两次时的最大值为max{profit,max{profits(i)}}。

求单个数组的组大利润算法复杂度为o(n),若在1~n-2位置分割分别计算时单个数组的最大利润时,此时算法的总的时间复杂度为o(n2),空间复杂度仍为o(1)。

实际上,会有很多重复计算。假设从第i个位置分割数组,profitsLeft(i)和profitsRight(i)分别表示该位置左右两侧数组利润最大值。用两个大小为n的数组profitsLeft和profitsRight记录i位置分割时左右两侧最大利润。则算法时间复杂度为o(n),空间复杂度也为o(n)

代码(C++)

class Solution {
public:
int maxProfit(std::vector<int>& prices) {
int N = prices.size();
vector<int> profitsLeft(prices.size(),0);
vector<int> profitsRight(prices.size(),0);
int profit = 0;
if(prices.size()>=2){
int min = prices[0];
for(int i =1;i<prices.size();i++){
min = min > prices[i] ? prices[i] : min;
profitsLeft[i] = prices[i] - min;
profitsLeft[i] = profit = profit > profitsLeft[i] ? profit : profitsLeft[i];
}
int max = prices[prices.size()-1];
for(int i = prices.size()-2;i>=0;i--){
max = prices[i] > max ? prices[i] : max;
profitsRight[i] = profitsRight[i-1] > max - prices[i] ? profitsRight[i-1] : max - prices[i];
}
for(int i =1;i<prices.size();i++){
profit = profit > profitsLeft[i] + profitsRight[i] ? profit :profitsLeft[i] + profitsRight[i];
}
}
return profit;
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: