精华在评论区。。。。
当时去面试的时候现场现写,憋了将近一个小时,用递归实现了,估计问题很多,不是人家怎么可能不要我,哈哈哈,开个玩笑;
思路就是新建一个长度为100数组array1,把前100个元素放进去,排个序,然后再把剩下的元素拿来跟array1里面的元素比较,大于的时候替换,等于的时候就跳出循环取下一个元素,遍历一遍大数组就能取出前100大的数来,没考虑到时间复杂度,心里想实现了就烧高香了,那还管得了那么多。
后来回来百度的时候才发现,有更简洁的办法 ,利用堆排实现
什么是堆排?具体请见下面大神的博客
传送门:数据结构——常见的十种排序算法
利用堆排实现
1.取前n个数,建立一个小根堆。建堆的时间复杂度为O(nlogn)
2.顺序读取后边的元素,如果该元素比堆顶的元素小,直接丢弃。如果大于堆顶的元素则替换它,然后调整堆,最坏的情况是每一次都需要调整堆。时间复杂度为O(mlogn)。m为数据总数,n表示前n大的数。
代码实现:
import java.util.Arrays;
/**
* @auther: shy
* @date: 2020/5/13 9:50
*/
public class TopN {
/**
* 找出数组arr中最大的前n个值,不要求这n个值有序
*/
public static int[] topN(int[] arr, int n) {
/**
* 构建堆积
*/
int[] list = new int[n];
// 在堆顶的始终是最小的值
for (int i = 0; i < n; i++) {
int t = i;
while (t != 0 && list[parent(t)] > list[t]) {
swap(list, t, t = parent(t));
}
}
/**
* 小顶堆
*/
for (int i = n, len = arr.length; i < len; i++) {
if (arr[i] >= list[0]) {
// 置换栈顶
list[0] = arr[i];
// 调整栈顶
int t = 0;
// left(t) < n 防止下标越界
while ((left(t) < n && list[t] > list[left(t)]) || (right(t) < n && list[t] > list[right(t)])) {
// 比较右节点和左节点值值,把小的节点值和父节点值对调
if (right(t) < n && list[right(t)] < list[left(t)]) {
swap(list, t, t = right(t));
} else {
swap(list, t, t = left(t));
}
}
}
}
return list;
}
private static void swap(int[] list, int i, int j) {
int tmp = list[i];
list[i] = list[j];
list[j] = tmp;
}
/**
* 父节点索引
*/
private static int parent(int i) {
return (i - 1) / 2;
}
/**
* 左孩子索引
*/
private static int left(int i) {
return 2 * i + 1;
}
/**
* 右孩子索引
*/
private static int right(int i) {
return 2 * i + 2;
}
public static void main(String[] args) {
int[] arr = new int[] { 1, 2,90,47, 23, 4, 5, 11,97,1009, 12, 13,66 ,100 ,87};
System.out.println(Arrays.toString(TopN.topN(arr, 4)));
}
}
代码并非本人所写,来自大佬的博客,大佬写的很好帖出来一起学习,地址不小心走丢。。。。。。。。。。。。。。