
思路:将给出的数按顺序排序,然后按顺序计算,如果前后差值为1,开始迭代计数,然后与最大值比较,如果大于就更新。时间复杂度要求O(NlogN)。1.可以使用set,set自带去重和排序功能,十分适合做本题。set底层为红黑树,建成一个树的时间复杂度为O(NlogN),空间复杂度为O(N),不过由于是结点,所以系数肯定会大一些;

也可以用另一种set的构造函数:

2.还有一种方法,先用sort对给定的数组进行排序,再用unique函数去重,然后再用erase函数删除无效数据,就达到了与set一样的效果,并且空间消耗要小一些,时间复杂度也是O(NlogN)。这里着重看一下unique的用法

std::unique 是 C++ STL <algorithm> 里的函数,用于 去除相邻的重复元素 ,只保留每个元素第一次出现的位置,并返回新逻辑末尾迭代器。它不会真正删除元素,只是将重复内容移动到后面 。要真正删除,需要配合 erase()。
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1, 1, 2, 2, 2, 3, 3, 4};
auto last = unique(v.begin(), v.end());
v.erase(last, v.end()); // 真的删除重复部分
for(int x : v) cout << x << " ";
}
输出:
1 2 3 4
只处理相邻重复
如果元素不连续,unique 不会帮你排序或去重:
vector<int> v = {3, 1, 2, 1, 2};
unique(v.begin(), v.end()); // 没有作用,因为相邻元素没重复
所以常见用法是:
sort + unique
重载支持自定义比较
unique(v.begin(), v.end(), [](int a, int b){
return abs(a - b) < 3; // 自定义"相等"规则
});
返回值
| 内容 | 解释 |
|---|---|
| 返回迭代器 | 指向去重后"逻辑有效区间的末尾" |
| 原容器长度不变 | 只是元素被移动,末尾部分无意义 |
举个例子看一看unique的过程:
1222344
索引: 0 1 2 3 4 5 6
数据: 1 2 2 2 3 4 4
设:
write = 0
read = 1
规则:
-
如果
v[read] != v[write]→ 表示新值,把它写进write+1位置,并write++ -
如果相等 → 跳过
| 步骤 | read | write | 判断 | 修改后数组(带解释) |
|---|---|---|---|---|
| 初始 | 1 | 0 | --- | 1 2 2 2 3 4 4 |
| Step1 | 1 | 0 | 2 != 1 → 写入 |
1 2 2 2 3 4 4(写入到原位置,无变化)→ write=1 |
| Step2 | 2 | 1 | 2 == 2 → 跳过 |
1 2 2 2 3 4 4 |
| Step3 | 3 | 1 | 2 == 2 → 跳过 |
1 2 2 2 3 4 4 |
| Step4 | 4 | 1 | 3 != 2 → 写入 |
写入 index=2 → 1 2 3 2 3 4 4 → write=2 |
| Step5 | 5 | 2 | 4 != 3 → 写入 |
写入 index=3 → 1 2 3 4 3 4 4 → write=3 |
| Step6 | 6 | 3 | 4 == 4 → 跳过 |
1 2 3 4 3 4 4 |