第一问:
对于只有一次买入卖出的最大收益可以参照http://blog.csdn.net/calmreason/article/details/7904062,已经将的非常详细了
第二问:
当时做完这种情况后,考官又提出如果可以买入卖出两次,如何在O(N)的时间复杂度下解决问题,当时没有想出来,结果就挂了,今天想把这个问题解决掉
思路大体是这样的,如果要买卖两次的话(这里允许在同一时间卖出再买入,但是不允许同一时间买入再卖出),必定是在某一个时间点的两边进行买入和卖出的,这样就可以把问题简化为在某一个时间点左右进行一次股票买入和卖出的最大收益了。
其中在某一个时间节点左侧的最大收益是可以通过O(N)的时间复杂度得到的,只要在第一问的基础上设置一个数组ret1List[] 来存放当前节点的最大收益就可以了。问题是如何接下来计算右边的最大收益,最后发现如果将数组从后到前来遍历,再设置一个数组ret2List[] 来存放当数组从后到前来遍历时当前的最小收益,那么-1 * ret2List[]的值就对应了右边的最大收益。最后再遍历一遍,找到ret1List[i] - ret2List[i]的最大值,就是所要求的结果
代码如下:
#include <iostream>
using namespace std;
#define LEN 100
int _tmain(int argc, _TCHAR* argv[])
{
int n;
cin >> n;
if(n < 3)
{
cout << "error input" << endl;
return -1;
}
int list[LEN];
int ret1List[LEN]; //存放从左向右遍历时每个节点的最大收益
int ret2List[LEN]; //存放从右到左遍历时每个节点的最小收益
for(int i = 0; i < n; i ++)
{
cin >> list[i];
}
int minNum = list[0];
int maxDifferent = list[1] - list[0];
for(int i = 1; i < n - 1; i ++)
{
if(list[i] < minNum)
{
minNum = list[i];
}
else if(list[i] - minNum > maxDifferent)
{
maxDifferent = list[i] - minNum;
}
ret1List[i] = maxDifferent;
}
int maxNum = list[n - 1];
int minDifferent = list[n - 2] - list[n - 1];
for(int i = n - 2; i > 0; i --)
{
if(list[i] > maxNum)
{
maxNum = list[i];
}
else if(list[i] - maxNum < minDifferent)
{
minDifferent = list[i] - maxNum;
}
ret2List[i] = minDifferent;
}
int max = ret1List[1] - ret2List[1];
for(int i = 1; i < n - 1; i ++)
{
if(max < ret1List[i] - ret2List[i])
{
max = ret1List[i] - ret2List[i];
}
}
cout << max << endl;
return 0;
}