例題8-7:唯一的雪花
題意:
給出 n個數,找到儘量長的一個序列,使得該序列中沒有重複的元素
思路:
對於該類段查找問題可以採用經典的滑動窗口方法,即維護一個窗口,窗口的左右邊界用兩個變量L,R代表,先增加R直到出現重複數字,再增加L,再增加R,直到R達到n
一、set 數據結構(將窗口內的數字動態存儲在set裏,然後進行判重即可,當窗口L增加時,在set中刪除該元素即可)代碼如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<list>
#include<deque>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const double eps = 1e-6;
const int INF = 1 << 30;
int T, n, m;
int a[maxn];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
}
int r = 0, l = 0, ans = 0;
set<int>s;
while(r < n)
{
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;
}
二、利用數組pre[i]表示第i個數的最近一個重複數的位置,初始值設爲-1,這裏需要開一個輔助數組,在掃描過程中維護該數組的數據並生成pre[i]數組,T[i]表示數字i掃描到當前的最大下標,由於本題數字規模較大,難以開下T[]數組,所以我們利用map代替,代碼如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<list>
#include<deque>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
const double eps = 1e-6;
const int INF = 1 << 30;
int T, n, m;
int a[maxn], last[maxn];
map<int, int>Map;
int main()
{
//freopen("o.txt","w",stdout);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
Map.clear();
for(int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
if(!Map.count(a[i]))last[i] = -1;
else last[i] = Map[a[i]];
Map[a[i]] = i;
}
int l = 0, r = 0, ans = 0;
while(r < n)
{
while(r < n && last[r] < l)r++;
ans = max(ans, r - l);
l++;
}
cout<<ans<<endl;
}
return 0;
}