1000000个不重复数排序——桶排序
题目描述
文件内有大约100万个不重复的数字,这些数字的值都在[1, 10000000]之间,除此之外,最后一行为数字-1,表示结束,请对除-1以外的其他数字顺序排序。
考虑
做题偶尔做到的,题干主要强调的内容,关键词不重复
、有固定范围
,看到这些条件,首先可以想到使用桶排序。
常规的快排以及对排等等,肯定是达不到时间要求,这个数据量相对一般排序来说太大了,考虑桶排序,直接上代码。
代码
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
/**
* * [一句话描述功能] 1,000,000个数字桶排序
* * @apiNote:
* * @author: Jarven
* * @version: 0.0.1
* * @since: 2021-4-29
*/
public class BucketSort {
//定义最大数据大小
private static final int DATASIZE = 10000000;
public static void main(String[] args) {
//处理输入数据
Scanner scanner = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
int sc = scanner.nextInt();
int[] intArr = new int[DATASIZE];
int len = 0;
for (int i = 0; sc != -1; i++) {
intArr[i] = sc;
sc = scanner.nextInt();
len = i;
}
//处理完成,输入的全部数据被提取
int[] resultArr = new int[len + 1];
System.arraycopy(intArr,0,resultArr,0,len + 1);
//计算用时
long time1 = System.currentTimeMillis();
getBucketSort(resultArr);
System.out.println(System.currentTimeMillis() - time1);
}
private static void getBucketSort(int[] intArr){
//第一步,取得数组的最大/最小值以及需要桶数
int maxNum = Arrays.stream(intArr).max().getAsInt();
int minNum = Arrays.stream(intArr).min().getAsInt();
int bucketNum = intArr.length;
//初始化桶数组
ArrayList<ArrayList<Integer>> bucket = new ArrayList<>(bucketNum);
for (int i = 0;i < bucketNum;i++){
bucket.add(new ArrayList<Integer>());
}
//判定intArr中每个数属于哪个桶,用最大值 - 最小值 + 1保证不溢出报IndexOutOfBounds
for (int i : intArr) {
int bucketID = (i - minNum) / (maxNum - minNum + 1) * bucketNum;
bucket.get(bucketID).add(i);
}
//对每个桶内的数据排序
StringBuilder sb = new StringBuilder("");
for (ArrayList<Integer> integers : bucket) {
Collections.sort(integers);
}
//处理输出,每个字符间使用空格排开
for (ArrayList<Integer> integers : bucket){
for (int i : integers){
sb.append(i).append(' ');
}
}
//删掉最后一个空格字符
sb.deleteCharAt(sb.length() - 1);
System.out.println(sb);
}
}
运行结果
我个人测试了大小为7M的输入文件,1,000,000个数字经过输入输出优化后,排序的总时间话费125ms,还是非常快的。