1、获取最大的K个数
原理:最大的k,使用小堆。小堆得top元素是当前堆里面最小的value,当比较列表下一个元素的时候,如果比top元素还大,那么与top直接交换,然后调整堆结构,保证堆顶是当前堆里面最小的值。
注意:堆得左右树不强调有序。
public static void main(String[] args) {
int[] intArray = {10, 11, 12, 13, 1, 17, 3, 4, 5, 6, 7, 16, 9, 14, 15, 8 };
int[] topKArr = topK(intArray, 4);
print(topKArr);
}
private static void print(int[] topKArr) {
for (int i = 0; i < topKArr.length; i++) {
System.out.print(topKArr[i] + ", ");
}
System.out.println();
}
/**
* 递归的调整
* @param arrayList
* @param index
* @param length
*/
public static void adjustHeap(int[] arrayList, int index, int length) {
//数组组成的堆,按照index确认左右子树。
int leftTree = index * 2 + 1;
int rightTree = index * 2 + 2;
int findIndex = index;
//找到最小的索引节点
if (leftTree < length && arrayList[leftTree] < arrayList[index]) {
findIndex = leftTree;
}
if (rightTree < length && arrayList[rightTree] < arrayList[findIndex]) {
findIndex = rightTree;
}
//如果获得的值不是当前节点,那么需要调整他的子树
if (index != findIndex) {
swap(arrayList, findIndex, index);
adjustHeap(arrayList, findIndex, length);
}
}
public static void swap(int[] array, int a, int b) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
public static void buildHeap(int[] array) {
int length = array.length;
for (int i = length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, length);
}
}
public static void setTop(int[] array, int top) {
array[0] = top;
adjustHeap(array, 0, array.length);
}
public static int[] topK(int[] array, int k) {
int[] top = new int[k];
for (int i = 0; i < k; i++) {
top[i] = array[i];
}
//先建堆,然后依次比较剩余元素与堆顶元素的大小,比堆顶小的,
//说明它应该在堆中出现,则用它来替换掉堆顶元素,然后沉降。
buildHeap(top);
for (int j = k; j < array.length; j++) {
int temp = top[0];
if (array[j] > temp) {
setTop(top, array[j]);
}
}
return top;
}
//输出
14, 15, 16, 17,
2、输出最小的K个数。
原理:最小的k个数,使用大堆。大堆得top元素是当前堆里面最大的value,当比较列表下一个元素的时候,如果比top元素还小,那么与top直接交换,然后调整堆结构,保证堆顶是当前堆里面最大的值。
package test.test.com.controller;
public class TestMain {
public static void main(String[] args) {
int[] intArray = {10, 11, 12, 13, 1, 17, 3, 4, 5, 6, 7, 16, 9, 14, 15, 8 };
int[] topKArr = topK(intArray, 4);
print(topKArr);
}
private static void print(int[] topKArr) {
for (int i = 0; i < topKArr.length; i++) {
System.out.print(topKArr[i] + ", ");
}
System.out.println();
}
/**
* 递归的调整
* @param arrayList
* @param index
* @param length
*/
public static void adjustHeap(int[] arrayList, int index, int length) {
//数组组成的堆,按照index确认左右子树。
int leftTree = index * 2 + 1;
int rightTree = index * 2 + 2;
int findIndex = index;
//找到最大的索引节点
if (leftTree < length && arrayList[leftTree] >arrayList[index]) {
findIndex = leftTree;
}
if (rightTree < length && arrayList[rightTree] > arrayList[findIndex]) {
findIndex = rightTree;
}
//如果获得的值不是当前节点,那么需要调整他的子树
if (index != findIndex) {
swap(arrayList, findIndex, index);
adjustHeap(arrayList, findIndex, length);
}
}
public static void swap(int[] array, int a, int b) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
}
public static void buildHeap(int[] array) {
int length = array.length;
for (int i = length / 2 - 1; i >= 0; i--) {
adjustHeap(array, i, length);
}
}
public static void setTop(int[] array, int top) {
array[0] = top;
adjustHeap(array, 0, array.length);
}
public static int[] topK(int[] array, int k) {
int[] top = new int[k];
for (int i = 0; i < k; i++) {
top[i] = array[i];
}
//先建堆,然后依次比较剩余元素与堆顶元素的大小,比堆顶大的,
//说明它应该在堆中出现,则用它来替换掉堆顶元素,然后沉降。
buildHeap(top);
for (int j = k; j < array.length; j++) {
int temp = top[0];
//如果堆定元素与即将进入的元素进行对比,大堆顶、
if (array[j] < temp) {
setTop(top, array[j]);
}
}
return top;
}
}
5, 4, 1, 3,