基于partition做的,当index!=k时一直while循环
?
?
如果index<k,在后面找
?
?
如果index>k,在前面找
?
?
另外最后的结果如果是0到k-1这k个数包括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的值为4,a[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;
}
}
?
?
?
?