【高效算法設計——滑動窗口】UVa 11572 Unique Snowflakes


題意:給定n個數,求最長的一段使得該段內沒有重復數字


思路:對於該類段查找問題可以采用經典的滑動窗口方法,即維護一個窗口,窗口的左右邊界用兩個變量L,R代表,先增加R直到出現重復數字,再增加L,再增加R,直到R達到n


那么我們需要一些數據結構來存儲一些數據,使得我們能在短時間內判斷窗口內是否出現重復數字


這里提供兩種方法,第一個是經典的set,將窗口內的數字動態存儲在set里,然后進行判重即可,當窗口L增加時,在set中刪除該元素即可,代碼如下

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>

using namespace std;

set<int>M;

int w[1000000+50];

int main()
{
int n,i,j,ans,l,r,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);

ans=0;
M.clear();

l=1;
r=1;
ans=1;
for(;r<=n;)
{
while(!M.count(w[r]) && r<=n)
{
M.insert(w[r]);
r++;
}
ans=max(r-l,ans);

M.erase(w[l]);
l++;
}
printf("%d\n",ans);
}

return 0;
}



方法二,也是解決本類問題的經典用法,利用數組pre[i]表示第i個數的最近一個重復數的位置,初始值設為-1,這里需要開一個輔助數組,在掃描過程中維護該數組的數據並生成pre[i]數組,T[i]表示數字i掃描到當前的最大下標,由於本題數字規模較大,難以開下T[]數組,所以我們利用map代替,代碼如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>

using namespace std;

set<int>M;

int w[1000000+50];

int main()
{
int n,i,j,ans,l,r,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);

ans=0;
M.clear();

l=1;
r=1;
ans=1;
for(;r<=n;)
{
while(!M.count(w[r]) && r<=n)
{
M.insert(w[r]);
r++;
}
ans=max(r-l,ans);

M.erase(w[l]);
l++;
}
printf("%d\n",ans);
}

return 0;
}




注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: