方法概述
要找出一个序列中当前元素中的最小元素,或是找出第i个元素之前比第i个元素小的元素值,
方法一:
遍历序列,得出上述问题的解。时间复杂度为O(n)。
方法二:
用一个栈存储当前元素中的最小值。栈的第i个元素存储的是序列从0~i的元素中的最小值。时间复杂度为O(1)。
要找出序列当前最小值,只需要弹出栈顶元素即可,要找出多个,只需要一直判断stack.top()<i是否成立,如果成立则继续弹出,直到条件不再成立。
示例:
例题:
炒股神器
大师的神器有两个功能:第一,设置N天为一个周期,除最后一天不买之外,其它天每天都买进且只买一支股票,做到细水长流;第二,每天买进股票的同时,把之前买进的且还留在手头上的股票,只要买进价格比当天交易额低,就立马卖出赚差价,见好就收。如果到最后一天还有没卖掉的,就全部出售。
在这里插入代码片
输入格式:
输入两行数据,第一行只有一个整数N (1<N≤1000000)。第二行有N个正整数,第i∈[1,N], 个数s ∈[1,10000]表示第i天的单支股票的交易额。数据间用空格分开,末尾的数后面没有空格。
输出格式:
输出一个整数,表示N天的股票交易总收益。
输入样例:
7
8 1 4 6 7 10 5
输出样例:
6
总支出:8+1+4+6+7+10 = 36
总收入:4+6+7+10+10+5 = 42
注:比如第一天买进的在第六天卖出,第二天买进的在第三天卖出
,。。。以此类推。
方法一:数组遍历法
最低级思路,这种方法时间复杂度过高,在数据过多的时候会超时
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
long long N;
cin >> N;
long long * ps = new long long [N];
long long sale = 0;
for(int i=0; i<N; i++)
{
cin >> ps[i];
if(i!=N-1)
{
for(int j=0; j<i; j++)
{
if(ps[j] < ps[i])
{
sale+=ps[i] - ps[j];
ps[j] = 999999;
}
}
}
else
{
for(int i=0; i<N-1; i++)
{
if(ps[i] != 999999)
{
sale += ps[N-1] - ps[i];
}
}
}
}
cout << sale;
system("pause");
return 0;
}
方法二:最小元素存储栈
运用一个栈存储当前元素中的最小值,在新买入一直股票后,先对比这只股票价格和栈顶元素,如果新股票价格比栈顶元素大,那么弹出栈顶元素,收入+=新股票价格,继续与栈顶元素比较,重复上述步骤,直到栈顶元素大于新股票价格或者栈为空,然后将新股票价格加入栈内。
#include <iostream>
#include <stdlib.h>
#include<stack>
using namespace std;
int main()
{
int N;
cin >> N;
stack<int> smaller;
int curr;
int sale = 0;
int buy = 0;
for(int i=0; i<N-1; i++)
{
cin >> curr;
buy += curr;
while(curr>smaller.top())
{
sale+=curr;
smaller.pop();
}
smaller.push(curr);
}
}
cin >> curr;
sale += curr * smaller.size(); //最后一天不买股票,全卖掉
cout << sale - buy;
system("pause");
return 0;
}
由此可见,最小元素存储栈在序列找最小元素或最大元素的问题中可以大大减小时间复杂度。