题目描述:
最开始用暴力法解决,后来终于体会到什么时间复杂度O(N^N)的……,自己测试数组中有30个以上的元素,就需要等半天了,更别说测试用例中一千多个元素了。参考官方题解中的java代码后,用C++实现,特总结如下:
/*方法一:暴力法(时间超时)
暴力法需要计算所有可能的交易组合相对应的利润,并找出其中最大的利润;
在未处理的子序列中不断使用递归函数去寻找最大利润。
这种方法:不仅时间复杂度高-O(N^N),并且还使用了递归函数,非常不好;而且我发现
这种方法容易想到,但是实现起来可没那么容易。
*/
int calculateMaxProfit(vector<int> &prices, int start)
{//调用此calculateMaxProfit函数使用递归暴力法
if(start >= prices.size())
return 0;
int maxProfit = 0;
for (int i = start; i < prices.size() - 1; i++)
{
int tempProfit = 0;
for (int j = i + 1; j < prices.size(); j++)
{
if (prices[i] < prices[j])
{
int profit = prices[j] - prices[i] + calculateMaxProfit(prices, j + 1);
if(profit > tempProfit)
tempProfit = profit;
}
}
if(tempProfit > maxProfit)
maxProfit = tempProfit;
}
return maxProfit;
}
/*方法二:峰谷法(官方题解)
把数组中的数字以折线图的形式反映,我们发现这就是有波峰和波谷的折线图。而我们要找最大利润,
其实就是我们要找到所有挨得最近的一组波谷和波峰差值的总和;
在这种情况下:只需要一次循环,不停的找某个波谷的值,然后紧接着找到离它最近的一个波峰的值,
他们的差值就是最大利润的一部分;然后接下去再找下一组波谷和波峰;
时间复杂度:O(N)
*/
int maxProfit_peak_valley(vector<int>& prices) {
int valley, peak, maxProfit = 0, index = 0;
int len = prices.size();
while(index < len - 1)
{
while (index < prices.size() - 1 && prices[index] >= prices[index + 1])
index++;//寻找波谷
valley = prices[index];
while (index < prices.size() - 1 && prices[index] <= prices[index + 1])
index++;//寻找波峰
peak = prices[index];
maxProfit += peak - valley;
}
return maxProfit;
}
/*方法三:一次遍历(官方题解)
这种方法是峰谷法的改进:在从头到尾循环遍历数组中每一个元素的时候,我们可以把处于升序排列的
子序列数组元素的差值依次相加。
时间复杂度:O(N)
*/
int maxProfit(vector<int> prices)
{
int maxProfir = 0;
for (int i = 1; i < prices.size(); i++)
if(prices[i] > prices[i - 1])
maxProfir += prices[i] - prices[i - 1];
return maxProfir;
}