先贴个题目:
以及原题链接:1210. 连号区间数 - AcWing题库
https://www.acwing.com/problem/content/description/1212/
这题我的第一反应是先枚举起始点和最终点,然后排序,然后因为一个差为1的数列必然有的性质就是ai-aj=i-j,因此暴力枚举然后排序判断,就能得到最终答案。代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 10010;
int list[N], tmp[N];
int main()
{
int n, sum = 0;
cin >> n;
sum += n;
for (int i = 1; i < n + 1; ++i)
cin >> list[i];
for (int i = 1; i < n; ++i)
for (int j = i + 1; j < n + 1; ++j)
{
int len = j - i + 1;
memcpy(tmp + 1, list + i, sizeof(int) * len);
sort(tmp + 1, tmp + len + 1);
if (tmp[len] - tmp[1] == len - 1)
{
sum++;
}
}
cout << sum;
return 0;
}
然后样例过了,然后提交,tle了,T-T。分析下时间复杂度,外面两层循环O(n方),里面sort(nlogn)肯定是超了,那咋办呢?因为题目中的N=1e4,所以我们要把算法优化到O(n方)然后我们就可以从sort做文章,我们不是排序吗?排序的意义是什么?找到片段的最小数和最大数不就完了,那我们直接优化,找两个变量max,min,每次找定起点后,每次终点往后一个数,就把那个数拿进来判断和最大最小两个数之间的关系,从而保证区间内局部最大最小数正确,然后判断是不是相符,问题就解决了,优化过后的代码如下:
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 10010;
int list[N], tmp[N];
int main()
{
int n, sum = 0;
cin >> n;
sum += n;
for (int i = 1; i < n + 1; ++i)
cin >> list[i];
int Max, Min;
for (int i = 1; i < n; ++i)
{
Max = list[i];
Min = list[i];
for (int j = i + 1; j < n + 1; ++j)
{
Max = max(Max, list[j]);
Min = min(Min, list[j]);
if (Max - Min == j - i)
sum++;
}
}
cout << sum;
return 0;
}
至于代码部分,没啥好说的。
by————2024.2.27刷题记录