紫书 第八章
输入一个长度为n的序列A,找到一个尽量长的连续子序列al-ar,使得该序列中没有相同元素。
设左端点为 L,右端点为R ,初始L = 0, R=0,R不断增加,只要在L和R中间没有出现过重复的数就一直增加。
O(nlogn)
代码如下:
#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 5;
int t, a[maxn], n;
int main(){
cin >> t;
while(t--){
cin >> n;
for(int i = 0; i < n; i++) cin >> a[i];
int l = 0, r = 0, ans = 0;
while(r<n){
set<int> s; //set来看看有没有重复数字
while(r < n && !s.count(a[r])) s.insert(a[r++]);
ans = max(ans, r - l);
s.erase(a[l++]);
}
cout << ans << endl;
}
return 0;
}
还可以用一个map求出last【i】,即下标i的“上一个元素的下标”。
代码如下:
#include <iostream>
#include <map>
using namespace std;
const int maxn = 100000 + 5;
int n, t;
map<int, int> cur;
int a[maxn], last[maxn];
int main() {
cin >> t;
while(t--) {
cur.clear();
cin >> n;
for(int i = 0; i < n; ++i) {
cin >> a[i];
if(!cur.count(a[i])) last[i] = -1;
else last[i] = cur[a[i]];
cur[a[i]] = i;
}
int l = 0, r = 0, ans = 0;
while(r < n) {
while(r < n && last[r] < l) r++; //如果上一个元素小于L,即不在区间中,那么r就可以加
ans = max(ans, r - l);
l++; //r加完以后 就左边开始加,加到右边 也可以加为止
}
cout << ans <<endl; //最后一个输出
}
return 0;
}