《剑指offer—面试题40:最小的k个数》——海量数据
注明:仅个人学习笔记
import java.util.ArrayList;
/**
*
*
*
* 最小的k个数 输入n个整数,找出其中最小的k个整数
* 方法一:可以将这n个数排序,最终得到排序后的前k个数即为所求
* 方法二:使用大小为k的容器,将数组前k个数先存放进去,然后遍历数组中的数和每次容器中的最大值比较,如果数组中的值小,则替换容器中的最大值
*
* 容器可以是最大堆,可以是ArrayList,也可以是红黑树
*
*/
public class Solution {
public ArrayList GetLeastNumbers_Solution(int[] input, int k)
{
ArrayList<Integer> list = new ArrayList<Integer>();
if (input.length < k || k == 0)
return list;
for (int i = 0; i < k; i++)// 初始化list,用数组中的前k个数,0——k-1
list.add(input[i]);
for (int i = k; i < input.length; i++)// 然后开始遍历数组剩余数,k——length-1,
{
int j = this.getMax(list);// 当前list中的最大值的索引
int temp = (Integer) list.get(j);// 当前list中的最大值
if (input[i] < temp)// 如果遍历到的数组中的数小于当前list中的最大值,则替换
list.set(j, input[i]);
}
return list;
}
public int getMax(ArrayList<Integer> list)
{
int max = list.get(0);
int j = 0;
for (int i = 0; i < list.size(); i++)
{
if (list.get(i) > max)
{
max = list.get(i);
j = i;
}
}
return j;
}
}
———————————大根堆———————————
https://www.nowcoder.com/profile/448404/codeBookDetail?submissionId=1505827
用最大堆保存这k个数,每次只和堆顶比,如果比堆顶小,删除堆顶,新数入堆。
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
public ArrayList GetLeastNumbers_Solution(int[] input, int k) {
ArrayList result = new ArrayList();
int length = input.length;
if(k > length || k == 0){
return result;
}
PriorityQueue maxHeap = new PriorityQueue(k, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
for (int i = 0; i < length; i++) {
if (maxHeap.size() != k) {
maxHeap.offer(input[i]);
} else if (maxHeap.peek() > input[i]) {
Integer temp = maxHeap.poll();
temp = null;
maxHeap.offer(input[i]);
}
}
for (Integer integer : maxHeap) {
result.add(integer);
}
return result;
}
}
关于海量数据处理
假设题目要求是从海量的数据中造出最小的k个数字,由于内存的大小是有限的,有可能不能把这些海量数据一次性全部载入内存。这个时候,我们可以从辅助存储空间(如硬盘)中每次读入一个数字,根据最小的k个数,判断这些数据是不是需要放入容器中,这种思路只要求内存能容下k个数即可。因此,它最适合的情形是n很大并且k较小的问题。
——form《剑指Offer》