题目链接:
3320 -- Jessica's Reading Problem (poj.org)
http://poj.org/problem?id=3320题意:
给定一个长度为 n的数组,数组元素代表每一页上的知识点,求覆盖到所有不同知识点的最小区间的长度。
思路:
不难想到这个题目用尺取法,采用快慢指针来求取最小区间长度。
首先统计知识点的个数:数组元素是Long Long类型,不能用普通数组作为标记数组,可采用map<long long ,int> m 来表示知识点的编号与个数的对应关系。
其次用循环来遍历数组,进行快慢指针求取。巧妙利用区间内知识点的个数与总个数的关系来进行尺取:在i与j区间内知识点的个数小于总知识点数,则j++,重新统计知识点数目; 知识点个数大于总知识点数,则i++,重新统计知识点数;
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e6+10;
map <long long ,int> m; //知识点
long long a[N];
int n;
int main(){
cin >> n;
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
m[a[i]] = 0;
}
int cnt = 1;
m[a[0]] = 1; //标记数组,表示在区间内知识点出现的个数
int ans =INF;
for(int i=0,j=0;j<n; ){
if(cnt != m.size()){ //区间知识点数目与总数目不等
j++; //j往后走,遍历后面的知识点
m[a[j]]++;
if(m[a[j]]==1)cnt++; //如果该知识点第一次出现,则cnt++
}else{
ans = min (ans ,j-i+1);
m[a[i]]--;
if(m[a[i]]==0) cnt--; //区间内无此知识点,则cnt--
i++; //i往前走
}
}
cout << ans ;
return 0;
}
同学写的尺取代码:

尺取模板:
for (int i=? ,j = ? ; i的控制条件 ; i++){
while(j的范围 && i与j的题意条件) {
j++;
//题意逻辑
}
//题意逻辑
}
文章讲述了如何使用尺取法和快慢指针优化求解POJ3320题中的最小覆盖区间长度问题,涉及数据结构如map的使用。
796






