题目链接
https://vjudge.net/problem/Aizu-ALDS1_1_D
题目大意
给出一列数, 输出最大值
题目的坑
看似很简单, 直接两层for循环就可以搞定了, 但这会超时。(因为我就是这么做的..0.0)
典型的错误示例...
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int N;
int a[200005];
int main()
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
scanf("%d", &a[i]);
int maxn = a[1] - a[0];
for (int i = 0; i < N-1; i++)
for (int j = i + 1; j < N; j++)
maxn = max(maxn, a[j] - a[i]);
cout << maxn << endl;
return 0;
}
如果用以上解法则时间复杂度约达到了 , 肯定是过不去的。所以得进行优化, 那这里怎么进行优化呢?
如果我们每找一次最大值, 并同时保存当前的最小值, 就可以少一个for循环, 时间复杂度约为, 可能这么说还不是太明白.
举个例子: 假如这里有一些数字 5,3,1,3,4,3 , 一开始我们取一个很小的数为最大值(比如maxn=-1e9),minn=5为最小值(只是一开始的预备处理, 后面会不断更新的), 现在进入for循环开始找最大值, 首先是3-5和-1e9比较取最大值, 那么现在的最大值是3-5(=-2), 同时保存当前的最小值, 即再加上一条语句, minn=(3,minn), 则此时最小值为3, 那么当进入下一次循环, 直接让1-3 就可以了, 还会让1-5吗,这就没意义了,因为3比5小, 减去越小的数字则结果会越大.
如果还不懂, 则要细细的品尝代码~
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int N;
int a[200005];
int main()
{
scanf("%d", &N);
for (int i = 0; i < N; i++)
scanf("%d", &a[i]);
int maxn = a[1]-a[0]; //这里我以a[1]-a[0]为初始的最大值
int minn = a[0];
for (int i = 1; i < N; i++)
{
maxn = max(maxn, a[i] - minn); //a[i]减去当前最小值的结果 就是当前的最大值
minn = min(a[i], minn);
}
cout << maxn << endl;
return 0;
}
如果你觉得这样开这么大的数组去存数据浪费内存的话, 其实还可以再一次优化, 可以减少空间复杂度(亲测可行^.^)
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int N;
int a;
int main()
{
scanf("%d", &N);
int maxn = (int)-1e9, minn;
for (int i = 0; i < N; i++)
{
scanf("%d", &a);
if (i == 0) //i==0 主要就是设置第一个数字为最小值, 便直接进入下一次循环
{
minn = a;
continue;
}
maxn = max(maxn, a - minn); //a[i]减去当前最小值的结果 就是当前的最大值
minn = min(a, minn);
}
cout << maxn << endl;
return 0;
}