1030 完美数列
- 给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
- 现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(<=10^5),是输入的正整数的个数, p <=(10^9)是给定的参数。第二行给出 N 个正整数,每个数不超过 10^9。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
代码实现:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));//buff加快读取速度
String[] buf = bf.readLine().split("\\s+");//用任意个空格分割字符串
int N = Integer.parseInt(buf[0]);//取得N
int p = Integer.parseInt(buf[1]);//取得p
ArrayList<Integer> list = new ArrayList<>();
buf = bf.readLine().split(" ");//读取数列
for (int i = 0; i < N; i++) {
list.add(Integer.parseInt(buf[i]));//把数列放到集合当中去
}
Collections.sort(list);
bf.close();
int count = 0;
for (int i = 0; i < N; i++) {
//循环的时候直接跳过count个数字
for (int j = i + count; j < N; j++) {
if(list.get(j) > list.get(i)*p){
//如果不满足是完美数列了,就退出里层循环
break;
}
if( j-i+1 > count){
//满足完美数列,并且该完美数列的个数大于前一个完美数列的个数,记录下这个数字,继续里层循环
count = j-i+1;
}
}
}
System.out.print(count);
}
}
运行结果:
这道题很遗憾最终结果还是有一个测试点未通过,在网上找了几个人的答案,也是测试点4未通过,这个问题暂时先放着。
总结:
1、最一开始我采用最常见的接收方式:Scanner类来接收数据,但是可以发现用时很长,影响到了答题效果,所以后来换成字节流高效读取数据;
2、刚开始我采用了两层循环,里层循环变量是外层循环变量+1,并定义一个数组用来存放每个数对应的它的最大完美序列个数,最终找到这个数组的最大值并输出;
3、但是很明显这样做效率很低,假如一轮外层循环结束,再次进行一轮里层循环的时候走了很多不必要的循环,最终想到了另一个解决方法:
在执行循环体的时候,先判断是否是完美序列,如果不是就直接退出当前循环(因为该序列已经是一个有序序列,后面的数字也一定不满足完美序列,如果满足完美序列,只需要定义一个count变量用来记录当前的完美序列数字个数,如果这次完美序列个数大于上次,就将这个最大值赋给count,最中循环结束,找到了最大个数。