PAT(B) 1030 完美数列 - C语言 - 滑动窗口 & 双指针

36 篇文章 0 订阅
27 篇文章 3 订阅

题目链接:1030 完美数列 (25 point(s))

给定一个正整数数列,和正整数 p p p,设这个数列中的最大值是 M M M,最小值是 m m m,如果 M ≤ m p M≤mp Mmp,则称这个数列是完美数列。

现在给定参数 p p p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。

输入格式:

输入第一行给出两个正整数 N N N p p p,其中 N N N ≤ 1 0 5 ≤10^5 105)是输入的正整数的个数, p p p ≤ 1 0 9 ≤10^9 109)是给定的参数。第二行给出 N N N 个正整数,每个数不超过 1 0 9 10^9 109

输出格式:

在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。

输入样例:

10 8
2 3 20 4 5 1 6 7 8 9

输出样例:

8

题解

如果用双层循环的话,肯定是会超时的。

需要先排序。再用滑动窗口(双指针)来解决此题。

不断移动右边界。然后用左边界向右移动不断试探。并记录最大值。

示例过程如下:
1、先升序排序

0123456789
12345678920

2、两个指针 l e f t left left r i g h t right right 指向第一个数据,最大长度 m a x L e n = 0 maxLen = 0 maxLen=0

12345678920
l e f t left left r i g h t right right

3、因为 1 ∗ 8 > 1 1 * 8 > 1 18>1,且 1 > m a x L e n 1 > maxLen 1>maxLen,所以 m a x L e n = 1 maxLen = 1 maxLen=1 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

4、因为 1 ∗ 8 > 2 1 * 8 > 2 18>2,且 2 > m a x L e n 2 > maxLen 2>maxLen,所以 m a x L e n = 2 maxLen = 2 maxLen=2 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

5、因为 1 ∗ 8 > 3 1 * 8 > 3 18>3,且 3 > m a x L e n 3 > maxLen 3>maxLen,所以 m a x L e n = 3 maxLen = 3 maxLen=3 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

6、因为 1 ∗ 8 > 4 1 * 8 > 4 18>4,且 4 > m a x L e n 4 > maxLen 4>maxLen,所以 m a x L e n = 4 maxLen = 4 maxLen=4 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

7、因为 1 ∗ 8 > 5 1 * 8 > 5 18>5,且 5 > m a x L e n 5 > maxLen 5>maxLen,所以 m a x L e n = 5 maxLen = 5 maxLen=5 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

8、因为 1 ∗ 8 > 6 1 * 8 > 6 18>6,且 6 > m a x L e n 6 > maxLen 6>maxLen,所以 m a x L e n = 6 maxLen = 6 maxLen=6 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

9、因为 1 ∗ 8 > 7 1 * 8 > 7 18>7,且 7 > m a x L e n 7 > maxLen 7>maxLen,所以 m a x L e n = 7 maxLen = 7 maxLen=7 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

10、因为 1 ∗ 8 = 8 1 * 8 = 8 18=8,且 8 > m a x L e n 8 > maxLen 8>maxLen,所以 m a x L e n = 8 maxLen = 8 maxLen=8 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

11、因为 1 ∗ 8 < 9 1 * 8 < 9 18<9,所以 l e f t left left 右移

12345678920
l e f t left left r i g h t right right

12、因为 2 ∗ 8 > 9 2 * 8 > 9 28>9 r i g h t right right 右移

12345678920
l e f t left left r i g h t right right

13、因为 2 ∗ 8 < 20 2 * 8 < 20 28<20 l e f t left left 右移

12345678920
l e f t left left r i g h t right right

14、因为 3 ∗ 8 > 20 3 * 8 > 20 38>20 r i g h t right right 右移, r i g h t = N right = N right=N,所以结束,因此最终结果是 8 8 8

C代码

/*********************************************************************
Score: 25
Problem: 1030
Compiler: C(gcc)
Run Time: 25ms
Version: 1.2
Author: wowpH
Date: 2019-11-22 21:38:27
From: https://www.cnblogs.com/wowpH/p/11914428.html
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>

#define MAX_N 100000

long long arr[MAX_N];// 乘法会超过int型范围

int compare(const void* a, const void* b);

int main(void) {
	int N, p;
	scanf("%d %d", &N, &p);
	for (int i = 0; i < N; ++i) {
		scanf("%lld", &arr[i]);
	}
	qsort(arr, N, sizeof(long long), compare);// 头文件stdlib.h
	int left = 0;
	int right = 0;
	int maxLen = 0;
	while (right < N) {
		while (left < N && arr[left] * p < arr[right]) {// mp>=M
			++left;
		}
		if (right - left + 1 > maxLen) {
			maxLen = right - left + 1;
		}
		++right;
	}
	printf("%d\n", maxLen);
	return 0;
}

int compare(const void* a, const void* b) {
	return *(int*)a - *(int*)b;// 升序
}

原文链接:https://www.cnblogs.com/wowpH/p/11914428.html


- End - wowpH - cnblogs -
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值