【PAT-A1085】Perfect Sequence(two pointers)

【题意】

给出N个10^5以下的正整数组成的序列,找出能使M <= m*p成立的最大序列元素数,其中M是目标序列的最大值,m为最小值。

【思路】

考虑到时间限制为200ms,N的最大值为10^5 所以时间复杂度不能超过 10^6量级即O(nlogn)的复杂度。

  • 首先对序列进行排序,复杂度O(nlogn)

  • 然后用two pointers两个指针分别指向最大值和最小值,然后判断M <= m*p是否成立,然后依次向中心移动两个指针直到第一个成立的地方然后退出,如果两点相遇都没有成立,输出0。

按照上面的思想写出来的代码最后一个测试点总过不去,开始怀疑是边界值的问题,但是再在特判边界值后还是过不去。因此怀疑是算法有漏洞。
仔细一想找出了原因和反例:假设i = 0, j = n- 1不能使上式成立,那么由于我的算法总是会先让i++,那么接下来判断的就是i = 1, j = n- 1,如果它也不能使上式成立则j++下一步比较的将是i = 1, j = n- 2.但是,假设i = 0, j = n - 1能使上式成立的话,那么我对算法就会忽略上面这种情况。

正确算法

考虑到如果a[j] <= a[i] * p 成立那么对[i,j]内的任意位置k a[k] <= a[i] * p 一定成立。让i和j都从最小值(左端)开始,让i不动,j不断右移直到不满足上式为止,更新这个过程中的最大长度。然后i右移一位,再让j从当前位置开始不断右移注意这里j不用再从i开始向右的原因就是刚刚说的。

【代码】

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
int main() {
	int p, n;
	int s[maxn]; 
	scanf("%d%d", &n, &p);
	for (int i = 0; i < n; i++)
	{
		scanf("%d", &s[i]);
	}
	sort(s, s + n);
	int i = 0, j = 0, maxl = 0;
	while (i < n && j < n)
	{
		while (j < n && (long long)s[i] * p >= s[j])
		{
			maxl = max(maxl, j - i + 1);
			j++;
		}
		i++;
	}
	printf("%d\n", maxl);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值