1、题目链接
https://www.patest.cn/contests/pat-a-practise/1085
2、题目分析
(1)题意:给出一串数字,然后给出一个数p,请从这串数字中找出可以存在的数字序列,序列中的最大值max与最小值满足max<=min*p;使得这样的序列包含的数字尽量最大
(2)分析:我们可以使用two pointers的方法来实现着一题。
3、问题
(1)在一次次的排除可以排除完的bug之后,我们会发现,有一个难以接受的问题。“时间限制”,对,我们可以看到如果使用下述的代码其余的测试点都会通过,但是会有一个时间超过的问题。代码如下:
#include <stdio.h>
#include <algorithm>
using namespace std;
#define size 100002
/*
1.使用two pointer
*/
int main(){
long long n,p;
scanf("%ld %ld",&n,&p);
int i ;
long long array[size];
for(i = 0;i<n;i++){
scanf("%ld",&array[i]);
}
sort(array,array+n);
int number = 0;//用来记录两者之间相差的数目
for(i = 0 ; i < n ; i++){
int j = n - 1;
while(j >= i){
if(number > (j - i +1)){//如果说number的值已经大于两者的距离,则不再比较
break;
}
else{
if(array[j] <= array[i] * p){//如果满足条件
if(number <(j - i + 1)){
number = j - i + 1;
}
break;//只要满足这个情况,就break掉
}
else{
j--;
}
}
}
}
printf("%d",number);
}
/*测试点
10 8
2 3 20 4 5 1 6 7 8 9
10 8
2 3 25 4 5 10 6 7 8 9
2 5
6 40
*/这里给出了几个测试点,可以供大家测试
(2)我们想想一下,我们这里先是对一串数字进行排序,即使用sort(array,array+n),然后从这个数组中找出满足题意的最长子序列。即如下代码实现的功能:
for(i = 0 ; i < n ; i++){
int j = n - 1;
while(j >= i){
if(number > (j - i +1)){//如果说number的值已经大于两者的距离,则不再比较
break;
}
else{
if(array[j] <= array[i] * p){//如果满足条件
if(number <(j - i + 1)){
number = j - i + 1;
}
break;//只要满足这个情况,就break掉
}
else{
j--;
}
}
}
} 但是,我们是否注意到,如果对于一个已经选择好的数字array[i],我们已经知道了它的最长子序列为number个。如果我们对array[i+1]中的j再从i开始, 则处理速度太慢。即会超时,所以我们从刚才那个处理array[i]的j值开始就可以。这样就会避免时间超时的问题。正确代码如下:
#include <stdio.h>
#include <algorithm>
using namespace std;
#define size 100002
/*
1.使用two pointer
*/
int main(){
long long n,p;
scanf("%ld %ld",&n,&p);
int i ;
long long array[size];
for(i = 0;i<n;i++){
scanf("%ld",&array[i]);
}
sort(array,array+n);
int number = 0;//用来记录两者之间相差的数目
int j = 0;
for(i = 0 ; i < n ; i++){
while(j < n){//高明之处在于j值保持不变,然后i值却往后推了一个
if(array[j] <= array[i] * p){//如果满足条件
number = max(number,(j - i + 1));
}
else if(array[j] > array[i] * p){
break;//如果是这种情况则跳出循环
}
j++;
}
}
printf("%d",number);
}
/*测试点
10 8
2 3 20 4 5 1 6 7 8 9
10 8
2 3 25 4 5 10 6 7 8 9
2 5
6 40
*/
















