最小的k个数 2.5

基于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;

}

}

?
?

?
?

时间: 2024-08-30 07:41:32

最小的k个数 2.5的相关文章

找到无序数组中最小的k个数

题目:给定一个无序整数数组arr,找到其中最小的k个数 要求:如果数组arr的长度为n,排序之后自然可以得到最小的k个数,此时时间复杂度与排序的时间复杂度相同均为O(NlogN),本题要求实现时间复杂度为O(NLogK). 1.O(NLogK)的方法,即一直维护一个有k个数的最大的大根堆,这个堆是目前选出的k个最小数,在堆里的k个元素中堆顶的元素是最大的一个. 接下来遍历整个数组,遍历的过程中看当前数是否比堆顶元素小.如果是,就把堆顶的元素替换成当前的数,然后从堆顶的位置调整堆,替换后堆的最大元

九度 1371 最小的K个数

题目描述:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行:第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度. 第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]. 输出: 对应每个测试案例,输出最小的k个数,并按从小到大顺序打印. 样例输入: 8 4 4 5 1 6 2 7 3 8 样例输出: 1 2 3 4 此题的不同之处是最后的输

找到n中最小的k个数

题目:n个数中,求最小的前k个数. 这道题在各个地方都看到过,在国内出现的频率也非常高. 解法: 1. brute force. O(k*n)复杂度: 2. sort.O(k+n*lgn)复杂度: 3. 最大堆.每次替代的是大小为k的最大堆的最大值.O(k+(n-k)lgk)复杂度. 4. 最小堆.和sort类似,只是建堆后只求前k次.O(n+k*lgn)复杂度.在网上看到一个优化,就是pop出第k小的数(堆顶)的时候,最多只需要调整k-1层(不需要调到堆底).所以可以优化到O(n+k^2).当

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

【剑指offer】 堆排序查找最小的K个数

上一篇 说了些堆的建立及其相关操作,这里看下用堆来解决数据量较大的时候,查找最小的k个数的情况.这里会用到上一篇中的函数. 我们先生存1千万个随机数,写到文件中: import random def randData(): with open('randint.txt', 'w') as fd: for i in range(1, 10000000): fd.write('%d ' %random.randint(1, 100)) if i % 100 == 0: fd.write('\r')

编程算法 - 最小的k个数 代码(C)

最小的k个数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用快速排序(Quick Sort)的方法求解, 把索引值(index)指向前k个数. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdio.h> #include <stdl

编程算法 - 最小的k个数 红黑树 代码(C++)

最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用红黑树(multiset), 每次替换最大的值, 依次迭代. 时间复杂度: O(nlogk). 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <iostream> #include <vector> #includ

找出最小的k个数

•已知数组中的n个正数,找出其中最小的k个数. •例如(4.5.1.6.2.7.3.8),k=4,则最小的4个数是1,2,3,4 •要求: –高效: –分析时空效率 •扩展:能否设计出适合在海量数据中实现上述运算? 方法一: 1 //利用最大根堆实现最小k个节点 2 //最大根堆特点:每个节点都比他左右孩子要大 3 //调整最大堆的时间复杂度为O(lnK),因此该算法(问题)时间复杂度为O(nlnK). 4 //思路:通过数组建堆 5 //规律:第i个节点的左孩子为2i+1,右孩子为2i+2 6

剑指OFFER之最小的K个数(九度OJ1371)

题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行: 第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度. 第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]. 输出: 对应每个测试案例,输出最小的k个数,并按从小到大顺序打印. 样例输入: 8 4 4 5 1 6 2 7 3 8 样例输出: 1 2 3 4 解题思路: 我们通过

最小的K个数

输入n个数,找出其中最小的k个数.例如输入4,5,1,6,2,7,3,8 这8个数,则最小的4个数是1,2,3,4. 解法一:O(n)的算法,只有当我们可以修改输入数组时可用 1 int Partitoin(int* input, int low, int high) 2 { 3 if (input == NULL || low < 0 || high < 0 || low > high) 4 { 5 return -1; 6 } 7 int temp = input[low]; 8 w