PAT乙级1030. 完美数列(25)

1030. 完美数列(25)
给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。
现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数N和p,其中N( <= 105)是输入的正整数的个数,p( <= 109)是给定的参数。第二行给出N个正整数,每个数不超过109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8

分析:我想的是先把这个数列按从小到大排列,然后算出当最小元素是n[0]的时候该完美数列多长,当最小元素是n[1]的时候该完美数列多长。。。。。每次都用max记录下最长的那个完美数列的长度。

但是在找最大元素的过程中我出现了点问题,每次最大元素都要从头开始找,举个栗子,比如当最小元素是a[3]时,我的最大元素就从a[3],a[4],a[5]。。。这样找下去,直到找到了那个最大的比如是a[6],然后继续下一个循环,当最小元素是a[4]的时候,我的最大元素又从a[4],a[5],a[6].。。。这样找下去。这样的结果就是超时,因为时间复杂度达到了O(n^2)

其实观察上面我找的过程发现是有不必要的循环的。当最小元素是a[4]的时候,最大元素可以不用再从a[4]再开始找起的,因为上一个循环已经说明了a[3]*p>=a[6],那么a[4]*p肯定也是大于a[6]的,所以我们从a[7]找起即可。这样时间复杂度就达到了O(n)

最后数组不要用int,因为数字很大,可以用long。

#include
#include
#include
using namespace std;
int main()
{
	int N, p;
	long  n[100000];
	int max=1, i, j=1;  				//i指向完美数列最小元素,j指向完美数列最大元素,max表示完美数列最大长度
	cin >> N >> p;
	for (i = 0; i < N; i++)
		cin >> n[i];
	sort(n, n + N);					//排序
	for ( i = 0;j				//循环从最小元素为第0个开始,当最大元素滑到最后一个循环结束
	{
		for (; n[i] * p >= n[j]&& j	//尽可能的让j往右滑动
		if (max < j - i)			//判断是否比之前记录的完美数列长度长。
			max = j - i;
	}
	cout << max;
}


你可能感兴趣的:(PAT乙级题目部分解析)