来看哈我们这道例题
我们第一种想法应该就是暴力求解,枚举每个子数组
当我们枚举第一个数的时候,我们要从第一个数开始挨个枚举每个结尾
如图,以第一个数开头的最长不重复数我们就枚举完了
然后我们让两个指针全部到第二个数
再枚举第二个数能到达的最长子数组
如图还是到这就停止了,我们再枚举第三个数
依旧是到这里停止,我们其实啊,没必要非得每次枚举都退回去,我们可以让l++,直到达到合法的区间之后,再继续往后枚举长度
也就是说 当我们到这个状态的时候,别让r退回去了,我们让左指针不断加加,直到达到一个合法的区间之后,再让r往后走
这道题,就算我们想用暴力枚举,我们也用不了的
因为暴力枚举时间复杂度是N平方,我们会超时的
而滑动窗口时间复杂度只是O(N),我们最差的情况就算l和r把数组都扫描了一遍,此时时间复杂度是N+N 也就是O(N)
我们再来捋一遍我们滑动窗口的步骤
step1:初始化,l=1 r=1 unordered map<int,int> mp;
step2:进窗口,r指针指向的元素在哈希表++
step3:判断是否为合法区间 即mp[a[r]]<=1→如果不合法就step5:出窗口 也就是不断让mp[a[l]]-- l++,直到mp[a[r]]<=1
step6:已经是合法区间了,我们更新长度
#include <iostream>
#include <unordered_map>
using namespace std;
const int N = 1e6+10;
int a[N];
int n;
int main()
{int T;cin >> T;while(T--){cin >> n;for(int i = 1;i<=n;i++){cin >> a[i];}unordered_map <int,int> mp;int l = 1,r = 1;int ret = 0;while(r<=n){mp[a[r]]++;//进窗口 while(mp[a[r]]>1)//判断 {mp[a[l]]--;//出窗口 l++;}ret = max(ret,r-l+1);//更新结果 r++;}cout << ret << endl;}return 0;
}