题目描述
有20个数组,每个数组有500个升序排列的数,求出这10000个数中前500个最大的数,并求复杂度。
解题思路
用一个大小为20的最大堆,通过维护这个堆,每次选出一个最大的数,如此往复500次,所以时间复杂度500 * log(20)
代码
这道题比较有意思的是利用最大最小堆求解,以及求解最大堆解决的复杂度。代码分为两个部分,第一部分是我自己写的一个简略最大堆作为基础数据结构: MaxHeap.java
package wheels;
/**
* 最大堆的简单实现
* 类比最小堆,在此主要是锻炼自己迅速写各式各样的轮子,再写一遍
* @author XZP
* 一组测试数据: 12 45 -11 69 1 95 9 78 64 21
*/
public class MaxHeap {
private int INF = -9999999; // 认为规定的最小值
private int[] arr;
public MaxHeap (int size) {
arr = new int[size + 1]; // 下标从1开始
for (int i = 0; i <= size; i++) {
// 牺牲空间和一定时间来保证数组能存零值
arr[i] = INF;
}
}
/**
* 向最大堆中插入一个元素使其任然满足最大堆
* @param data 待插入数据
* @return 成功为true,失败将打印异常栈
*/
public boolean push(int data) {
int index = this.index();
try {
this.arr[index] = data;
siftup(index); // 插入数组末尾之后需要向上调整使其满足最大堆
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
return true;
}
/**
* @return 数组能存储的最大size
*/
public int size() {
return arr.length - 1;
}
/**
* 获取当前能插入值得数组下标
* @return 数组中已有值长度 + 1
*/
private int index() {
int usedLength = 0;
for (int i = 1; i <= this.size(); i++) {
if (this.arr[i] != INF) {
usedLength++;
}
}
return usedLength + 1;
}
/**
* 从最小堆中取最小的那个元素,并调整使其一直满足最小堆
* @return 数组不为空则返回最小的元素,否则返回人为规定的INF值
*/
public int pop() {
if (!isLegal(1)) {
// 每次取第一个元素(下标值为1