describe
蜗牛在制定今天的旅游计划,有 n 个景点可选,它已经把这些景点按照顺路游览的顺序排
成一排了,每个地方有相应的景观,这里用一个整数表示。
蜗牛希望选取连续的一段景点,还要选出来的每一个景点的景观都不同,问它最多能选出
多少个景点进行旅游。
limit
time | memory |
---|---|
1000ms | 524288K |
输入格式
第一行,一个正整数 n(1≤n≤10 ^ 5)
第二行,包含 n 个正整数 ai (1≤ai≤10 ^ 6),第 i 个整数表示第 i 个景点的景观
输入样例
5
1 2 3 2 1
输出格式
输出一行,包含一个整数,表示蜗牛最多能选出的景点数
输出样例
3
解析
本题的原型为求一个字符串中最长的不重复子串,使用 滑动窗口 算法解决
将输入的5个数1 2 3 2 1保存到容器中
在vector容器上面维护一个滑动窗口set(推荐unordered_set);满足条件则窗口增大,不满足
则缩小,途中记录区间大小,输出最终结果3,本题也可用双指针来维护窗口,效率更高.
c++代码
#include <iostream>
using namespace std;
#include <set>
#include <vector>
//需要被访问的数据或字符串
vector<int> vect;
int temp;
int ans;
//窗口
set<int> uset;
int main(){
//保存输入数据
int a;
cin>>a;
while(a--){
cin>>temp;
vect.push_back(temp);
}
vector<int>::iterator left=vect.begin();
vector<int>::iterator right=vect.begin();
vector<int>::iterator ed=vect.end();
//while跳出循环时,right==ed
while(right!=ed){
//判断当前right指向是否满足,不满足则跳出循环,此时right指向不满足的地方
while(!uset.count(*right)&&right!=ed){
uset.insert(*right);
right++;
}
//记录窗口大小
temp=right-left;
ans=max(ans , temp);
//缩小窗口,退出循坏时,left指向不包含right的地方
while(uset.count(*right)&&left<right){
uset.erase(*left);
left++;
}
}
cout<<ans;
return 0;
}
!
- 窗口是一个左闭右开的区间,即用right指针指向的地方是不满足条件的,流入到下一次外循环中,left则不断的缩小.左闭右开时,right-left 即可求出区间长. 即[1,2,3,4,5), 区间长为5-1=4;
- 对while()循坏的跳出条件需要熟悉,while(!uset.count(*right)&&right!=ed)
当uset.count(*right)或right==ed时跳出本循环,此时right指向的是容器中已有的值,或者end().即1 2 3 2 1,right此时指向2.再如left指针,跳出循环时,即1 2 3 2 1,left此时指向3.