windo

windo

题目描述:

给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,
你只能见到窗口的K个数,每次窗体向右移动一位,如下表: 

Windo position                Min value   Maxvalue

[ 1 3  -1 ] -3  5 3  6  7       -1         3

1  [3  -1  -3]  5 3  6  7       -3         3

1  3  [-1  -3  5]  3 6  7       -3         5

1  3  -1  [-3 5  3]  6  7       -3         5

1  3  -1  -3  [5 3  6]  7       3          6

1  3  -1  -3  5  [3  6  7]       3         7

你的任务是找出窗口在各位置时的 max value,min value. 

输入格式:

第 1 行n,k,
第 2 行为长度为 n 的数组 

输出格式:

2 行,
第 1 行每个位置的 min value,
第 2 行每个位置的 max value 

样例输入:

8  3

1  3  -1  -3 5  3  6  7

样例输出:

-1  -3  -3  -3  3  3

3  3  5  5  6  7

数据范围:

20%: n<=500;  
50%:  n<=100000; 
100%:  n<=1000000; 

k<=n;

 时间限制:

三秒(表示程序两秒就能过)


嗯…当我做这道题的时候,lzh学长告诉我这道题是要用单调队列做的…当时还没有学单调队列。然而在于我不信邪,偏要用数组做。//不能多次测试的时候别学我

 嗯...偏偏在于我真的试出来了,最开始没有优化的时候过了五组。优化了一下,九组,当时耗时还是3秒,最后的优化终于过而且不到两秒。

嗯...前面废话请自行省略...我只是过来表达一下激动的心情。好了下面上代码:

最初:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{
	/*freopen("00.in","r",stdin);
	freopen("00.out","w",stdout);*/
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>nn[i];
	for(int i=1;i<=n-k+1;i++)
	{
		int maxx=-10000000,minn=10000000;
		for(int j=i;j<i+k;j++)
		{
			if(nn[j]>maxx)maxx=nn[j];
			if(nn[j]<minn)minn=nn[j];
		}
		mn[i]=minn; mx[i]=maxx;
	}
	for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';
	cout<<endl;
	for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';
	return 0;
}
第一次优化:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{
	/*freopen("00.in","r",stdin);
	freopen("00.out","w",stdout);*/
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>nn[i];
	int maxx=-10000000,minn=10000000;
	for(int i=1;i<=k;i++)
	{
		if(nn[i]>maxx)maxx=nn[i];
		if(nn[i]<minn)minn=nn[i];
	}
	mn[1]=minn; mx[1]=maxx;
	for(int i=2;i<=n-k+1;i++)
	{
		if((maxx==nn[i-1])||(minn==nn[i-1]))
		{
			maxx=-10000000,minn=10000000;
			if(maxx<nn[i-1+k]) maxx=nn[i-1+k];
			if(minn>nn[i-1+k]) minn=nn[i-1+k];
			for(int j=i;j<i+k;j++)
			{
				if(nn[j]>maxx)maxx=nn[j];
				if(nn[j]<minn)minn=nn[j];
			}
		}
		else
		{
			if(maxx<nn[i-1+k]) maxx=nn[i-1+k];
			if(minn>nn[i-1+k]) minn=nn[i-1+k];
		}
		mn[i]=minn; mx[i]=maxx;
	}
	for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';
	cout<<endl;
	for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';
	return 0;
}
最终优化:

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int nn[1000100],mn[1000100]={},mx[1000100]={};
int main()
{
	/*freopen("00.in","r",stdin);
	freopen("00.out","w",stdout);*/
	std::ios::sync_with_stdio(false);
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>nn[i];
	int maxx=-10000000,minn=10000000;
	for(int i=1;i<=k;i++)
	{
		if(nn[i]>maxx)maxx=nn[i];
		if(nn[i]<minn)minn=nn[i];
	}
	mn[1]=minn; mx[1]=maxx;
	for(int i=2;i<=n-k+1;i++)
	{
		if((maxx==nn[i-1])||(minn==nn[i-1]))
		{
			maxx=-10000000,minn=10000000;
			if(maxx<nn[i-1+k]) maxx=nn[i-1+k];
			if(minn>nn[i-1+k]) minn=nn[i-1+k];
			for(int j=i;j<i+k;j++)
			{
				if(nn[j]>maxx)maxx=nn[j];
				if(nn[j]<minn)minn=nn[j];
			}
		}
		else
		{
			if(maxx<nn[i-1+k]) maxx=nn[i-1+k];
			if(minn>nn[i-1+k]) minn=nn[i-1+k];
		}
		mn[i]=minn; mx[i]=maxx;
	}
	for(int i=1;i<=n-k+1;i++) cout<<mn[i]<<' ';
	cout<<endl;
	for(int i=1;i<=n-k+1;i++) cout<<mx[i]<<' ';
	return 0;
}


其实看了会发现第二次与最后一次只差了一点,强烈推荐一个好用的东西:

std::ios::sync_with_stdio(false);

可以去百度一下这是什么。效率特别高,别问我为什么,我也不知道。


好了接下来来说一下我的思路,最初始的,也就是搜索,一次一次搜。


改过之后的也就是先判断每次去掉的是不是最大或最小,不是什么都好说,看新增进来的有没有比最大的大或者比最小的小。没有的话还是在数组里存原来的最大最小。有的话那也就是赋值再存。

但是当去掉的是最大或者最小的时候,再查找一遍(这里应该是可以优化的,但是怪我有点懒)。

最后输出。就这样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值