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

[leetcode] best time to buy and sell stock

2014-10-14 16:55 204 查看
题目:The best time to buy and sell stock (I) (II)  (III)

题目描述:

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

<问题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;

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

<问题3>Design an algorithm to find the maximum profit. You may complete at mosttwo transactions.

Note:

You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

 

解题思路:题目大意为在给定一个值序列,要求从中取出满足题意的序列。这些值代表价格,所以一定都大于0。

问题一相当于是从这组序列中取出两个值,使得后者减去前者的差最大;

问题二相当于从这个序列中抽出一个序列,并且给每个数加上符号,使得正负号交替,且第一个数带负号。

使得这个序列求和最大。

问题三相当于问题二中只允许最多取出四个值,组成一个序列。

在题目中,运行时间要求必须为O(n)。通过divide-and-conquer的方法会超时,必须要通过动态规划发方法进行求解。

(I)下面对第一个问题进行分析:

假设用P(i)表示前i个元素形成的序列得到的最大profit。那么第i+1个值之后会有什么改变呢?

假设第i+1个值与前i个中的最小值min的差大于P(i)的话,那么P(i + 1) = prices[i + 1] - min[i - 1];

如果小于P(i)的话,那么P(i + 1) = P(i). 即加入第i + 1个元素并不影响最终的profit.

算法中需要保存P[i - 1]和min[i - 1],分别表示前i个元素组成的序列的最大Profit 和 序列中的最小值。为了简单,代码中用结构体的方式存储。

(II)下面对第二个问题进行分析:

这个问题的算法相对简单。就相当于从原来的序列中得到所有的极小值和极大值的交替序列,然后分别求差,再求和。

如下图所示,对相邻的极值点求差,用极大值点减去极小值,最后将这些差求和。大体思想是这样的,至于实现的话可以有 一些技巧。



(III)下面对第三个问题进行分析:

第三个问题也用动态规划的方式进行求解,只是麻烦一点。由于最终交易次数不能大于2次,所以只能是一次或两次。那么我们可以这样想,如果是两次交易,那么可以将这个序列分成两个序列first[0...i]和second[i + 1, ... end]。假设第一次交易来自first序列,第二次交易来自second序列。只需要分别用动态规划的方式求取这两个序列,然后看在哪个节点处分开可以得到最大的profit。即profit = max {first[0...i]
+ second[i + 1, ...end]} for all i。

代码在实现的过程中采用了不同的表示方式,但思想就如上所述。

(I)

class Solution {
public:
struct node{
int profit;
int min;
node(int profit, int min) :profit(profit), min(min){};
};
int maxProfit(vector<int> &prices) {
int size = prices.size();
if(size == 0){
return 0;
}
vector<node*> record;
record.push_back(new node(0, prices[0]));
for (int i = 1; i < size; i++){
int min;
int temp;
if (prices[i] < record[i - 1]->min){
temp = record[i - 1] ->profit;
min = prices[i];
}
else{
temp = prices[i] - record[i - 1]->min;
if (temp < record[i - 1]->profit)
temp = record[i - 1]->profit;
min = record[i - 1]->min;
}
record.push_back(new node(temp, min));
}
return record[size - 1]->profit;
}


(II)

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

 

(III)

class Solution {
public:
struct leftnode{
int profit;
int min;
leftnode(int profit, int min) :profit(profit), min(min){};
};
struct rightnode{
int profit;
int max;
rightnode(int profit, int max) :profit(profit), max(max){};
};
int maxProfit(vector<int> &prices) {
int size = prices.size();
if(size == 0)
return 0;
vector<leftnode*> leftToRight;
vector<rightnode*> rightToLeft;
leftToRight.push_back(new leftnode(0, prices[0]));
rightToLeft.push_back(new rightnode(0, prices[size - 1]));
for (int i = 1; i < size; i++){
int min;
int temp;
if (prices[i] < leftToRight[i - 1]->min){
temp = leftToRight[i - 1] ->profit;
min = prices[i];
}
else{
temp = prices[i] - leftToRight[i - 1]->min;
if (temp < leftToRight[i - 1]->profit)
temp = leftToRight[i - 1]->profit;
min = leftToRight[i - 1]->min;
}
leftToRight.push_back(new leftnode(temp, min));
}
for (int i = 1; i < size; i++){
int max;
int temp;
if (prices[size - i - 1] > rightToLeft[i - 1]->max){
temp = rightToLeft[i - 1]->profit;
max = prices[size - i - 1];
}
else{
if (rightToLeft[i - 1]->profit < rightToLeft[i - 1]->max - prices[size - i - 1]){
temp = rightToLeft[i - 1]->max - prices[size - i - 1];
}
else{
temp = rightToLeft[i - 1]->profit;
}
max = rightToLeft[i - 1]->max;
}
rightToLeft.push_back(new rightnode(temp, max));
}
int profit = 0;
for (int i = 0; i < size; i++){
if (profit < leftToRight[i]->profit + rightToLeft[size - i - 1]->profit){
profit = leftToRight[i]->profit + rightToLeft[size - i - 1]->profit;
}
}
if (profit < leftToRight[size - 1]->profit)
profit = leftToRight[size - 1]->profit;
return pro
4000
fit;
}
};


 

';// get html// ========var _html = _response;// normalize// =========_html = _html.replace(/<\s+/gi, '<');_html = _html.replace(/\s+>/gi, '>');_html = _html.replace(/\s+\/>/gi, '/>');// remove// ======_html = _html.replace(/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息