最小的k个数 2.5

基于partition做的,当index!=k时一直while循环

   

如果index<k,在后面找

   

如果index>k,在前面找

   

另外最后的结果如果是0k-1k个数包括k-1的话,那么开始k-1传入数组

   

如果不包括k-1的话,那么可以不用减1

   

复杂度为NlogN

   

另外有NlogK的算法,利用最小堆

   

利用partition的解法

   

package maxKNum_2_5;

   

public class MinKNum_2_5 {

static int minK(int[] a, int k) {

k = k - 1;

int index = partition(a, 0, a.length - 1);

while (index != k) {

if (index < k) {

index = partition(a, index + 1, a.length - 1);

} else {

index = partition(a, 0, index - 1);

}

}

return index;

}

   

static int partition(int[] a, int left, int right) {

int i, j, t, key;

key = a[left];

i = left;

j = right;

while (i < j) {

while (a[j] > key && i < j)

j--;

while (a[i] <= key && i < j)

i++;

if (i != j) {

t = a[i];

a[i] = a[j];

a[j] = t;

}

}

a[left] = a[i];

a[i] = key;

return i;

}

   

public static void main(String[] args) {

// TODO Auto-generated method stub

int[] a = { 5, 4, 2, 3, 1, 2, 4, 5, 6 };

// System.out.println(partition(a, 0, a.length - 1));

for (int i = 0; i < a.length; i++) {

System.out.print(a[i]);

}

System.out.println();

System.out.println(minK(a, 3));

for (int i = 0; i < a.length; i++) {

System.out.print(a[i]);

}

System.out.println();

}

   

}

   

利用最小堆的解法

   

   

public class MinHeap {

   

private int[] data;

   

public MinHeap(int[] data) {

this.data = data;

buildHeap();

}

   

// 完全二叉树只有数组下标小于或等于 (data.length) / 2 - 1 的元素有孩子结点,遍历这些结点。

// *比如上面的图中,数组有10个元素, (data.length) / 2 - 1的值为4a[4]有孩子结点,但a[5]没有*

private void buildHeap() {

// TODO Auto-generated method stub

for (int i = (data.length) / 2 - 1; i >= 0; i--) {

heapify(i);

}

}

   

private void heapify(int i) {

// TODO Auto-generated method stub

int left_index = left(i);

int right_index = right(i);

// 表示 根结点、左结点、右结点中最小的值的结点的下标

int min_index = i;

if (left_index < data.length && data[left_index] < data[min_index]) {

min_index = left_index;

}

if (right_index < data.length && data[right_index] < data[min_index]) {

min_index = right_index;

}

if (i == min_index) {

return;

}

swap(i, min_index);

heapify(min_index);

}

   

private void swap(int i, int min_index) {

// TODO Auto-generated method stub

int temp = data[i];

data[i] = data[min_index];

data[min_index] = temp;

}

   

private int right(int i) {

// TODO Auto-generated method stub

return 2 * i + 2;

}

   

private int left(int i) {

// TODO Auto-generated method stub

return 2 * i + 1;

}

   

// 获取堆中的最小的元素,根元素

public int getRoot() {

return data[0];

}

   

// 替换根元素,并重新heapify

public void setRoot(int root) {

data[0] = root;

heapify(0);

}

   

public static void main(String[] args) {

// TODO Auto-generated method stub

int data[] = { 2, 3, 4, 5, 1 };

MinHeap minHeap = new MinHeap(data);

int root = minHeap.getRoot();

System.out.println(root);

for (int i = 0; i < data.length; i++) {

System.out.println(data[i]);

}

}

   

}

   

public class TopK

{

public static void main(String[] args)

{

// 源数据

int[] data = {56,275,12,6,45,478,41,1236,456,12,546,45};

   

// 获取Top5

int[] top5 = topK(data, 5);

   

for(int i=0;i<5;i++)

{

System.out.println(top5[i]);

}

}

   

// data数组中获取最大的k个数

private static int[] topK(int[] data,int k)

{

// 先取K个元素放入一个数组topk

int[] topk = new int[k];

for(int i = 0;i< k;i++)

{

topk[i] = data[i];

}

   

// 转换成最小堆

MinHeap heap = new MinHeap(topk);

   

// k开始,遍历data

for(int i= k;i<data.length;i++)

{

int root = heap.getRoot();

   

// 当数据大于堆中最小的数(根节点)时,替换堆中的根节点,再转换成堆

if(data[i] > root)

{

heap.setRoot(data[i]);

}

}

   

return topk;

}

}

   

   

原文地址:https://www.cnblogs.com/keedor/p/4397661.html