嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法

嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法

点我进入OJ题目详情

题意

给你一串数,让你求长度最长的子串,这个字串满足里面没有重复出现的数字。

解题思路

使用一个标记数组,来标记每个数的第一次出现的位置,然后进行下面的模拟,详细看代码实现吧。

自己当时憨憨,没有想到需要进行离散化,第一次提交后返回Runtime Error后立刻意识到需要进心离散化,但是没时间了,哎,太可惜了。当然做这道题时,自己思路也不是很清晰,导致Debug了好长时间。

后来想了想,这个思路不就是使用尺取嘛。

代码实现

//尺取,代码更加简洁
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 1e6+7;
int num[maxn];
map<int, int> mp;
int main()
{
    int n;
    while(scanf("%d", &n) != EOF)
    {
        int ans = 0, l=1;
        mp.clear();
        for (int i = 1; i <= n; i++)
            scanf("%d", &num[i]);
        for (int r = 1; r <= n; r++)
        {
            mp[num[r]]++;
            while(mp[num[r]] > 1)
            {
                mp[num[l]]--;
                l++;
            }
            ans = max(r - l +1, ans);
        }
        printf("%d
", ans);
    }
    return 0;
}
//这个是自己思路清晰后写的代码,思路将相当与两个指针
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector> 
using namespace std;
const int maxn=1e6+7;
vector<int> v;
int a[maxn], vis[maxn];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		while(!v.empty()) v.pop_back() ; //清空上次的数据
		for(int i=1; i<=n; i++)
			vis[i]=0; //初始化
		for(int i=1; i<=n; i++)
		{
			scanf("%d", &a[i]);
			v.push_back(a[i]);	
		}		
		sort(v.begin() , v.end() );
		v.erase(unique(v.begin() , v.end() ), v.end() ); //这行和上一行是进行离散化
		for(int i=1; i<=n; i++)
		{
			a[i]=lower_bound(v.begin() , v.end() , a[i])-v.begin()+1;
			if(vis[a[i]]==0)//这里只记录第一次数字出现的位置 
				vis[a[i]]=i;
		}
		int i, begin=1, ans=0;//begin相当于左指针
		for(i=1; i<=n; i++)//这里的i相当于右指针
		{
			if(vis[a[i]]!=i)
			{
				if(vis[a[i]] < begin) //如果第一次出现的位置,小于左指针指向的位置,那么就可以直接更改标记数组就行了,这里可以用笔和纸模拟一下就可以了。
				{
					vis[a[i]]=i;
				}
				else 
				{
					ans=max(ans, i-begin); //i-begin是长度
					begin=vis[a[i]]+1;//更改左边的位置
					vis[a[i]]=i; //更改标记数组
				}
			}
		}
		ans=max(ans, i-begin); //这里最后一次也需要进行判断一次
		printf("%d
", ans); 
	} 
	return 0;
}
//这里加了离散化就过来,还是自己太菜了!
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
int a[maxn];
int vis[maxn];
vector<int> v;
int main()
{
	int n;
	while(scanf("%d", &n)!=EOF)
	{
		while(!v.empty()) v.pop_back() ;
		for(int i=1; i<maxn; i++)
			vis[i]=0; 
		for(int i=1; i<=n; i++)
		{
			scanf("%d", &a[i]);
			v.push_back(a[i]);
		}
		sort(v.begin(), v.end());
		v.erase( unique(v.begin(), v.end() ), v.end() );
		for(int i=1; i<=n; i++)
		{
			int tmp=lower_bound(v.begin(), v.end() , a[i]) - v.begin() +1;
			a[i]=tmp;
			if(vis[tmp]==0)
				vis[tmp]=i;
		}
		int ans=0, tmp=0, begin=1, flag=0;
		for(int i=1; i<=n; i++)
		{
			flag=0;
			if(vis[a[i]]!=i && vis[a[i]]!=0)
			{
				if(vis[a[i]]>=begin)
				{
					ans=max(tmp, ans);
					tmp++;
					if(vis[a[i]]==begin)
						tmp=tmp-1;
					else 
						tmp=tmp-vis[a[i]]+begin-1;
					begin=vis[a[i]]+1;
					flag=1;
				}
				vis[a[i]]=i;
				if(flag==0)
					tmp++;
			}
			else{
				tmp++;
			}
		}
		ans=max(ans, tmp);
		printf("%d
", ans);
	}
	return 0;
}
欢迎评论交流!
原文地址:https://www.cnblogs.com/alking1001/p/11619400.html