30 - 找出最小的k个数

题目描述:http://ac.jobdu.com/problem.php?pid=1371

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。



第一种思路:

如上一题中,用快速排序中的划分函数,划分元素最终下标index小于K,划分[index+1, n];划分元素最终下标index大于K,划分[0, index-1]; 找到划分元素下标是K时,停止,此时0 ~ K-1 为最小的K个数

时间复杂度O(n),缺点是会修改原数组数据,没有办法处理海量数据。

第二种思路:

使用容器,保存K个数,继续遍历数组,当数组元素小于容器中的最大数,用该数替换最大数,当遍历完成时,容器中保存的K个数,即最小的K个数。

我们需要一直得到K个数中的最大值,用最大堆作为容器。

STL中没有现成的最大堆容器,我们可以用set,它是用红黑树实现的并且是有序的 ,插入和删除都是O(lg n); 默认set的第一个元素是最小值,我们传入功能函数,实现最大堆。

时间复杂度O(nlgn),空间占用O(K)

#include <iostream>
#include <set>
#include <functional> // 功能函数 greater,less等
using namespace std;
typedef multiset<int, greater<int> > MaxHeap; //最大堆
void FindMinKNums(int* nums, int k, int length, MaxHeap &result) {
    if (nums == NULL || k <= 0 || length <= 0 || k > length)
        return;
    result.insert(nums, nums + k);
    MaxHeap::iterator max_iter = result.begin();
    for (int i = k; i < length; i++) {
        max_iter = result.begin();
        if (nums[i] < *max_iter) {
            result.erase(max_iter);
            result.insert(nums[i]);
        }
    }
}
int main() {
    int nums[] = { 4,5,1,6,2,7,3,8 };
    int length = sizeof(nums) / sizeof(nums[0]);
    int k = 5;
    MaxHeap result;
    FindMinKNums(nums, k, length, result);
     for (MaxHeap::iterator iter = result.begin(); iter != result.end(); iter++)
         cout << *iter << endl;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 22:20:31

30 - 找出最小的k个数的相关文章

找出最小的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

数组中找出最小的K个数

题目 给出一个数组,找出K个最小的值 例如给出数组{5,2,4,3,1},给定K值3,则输出结果为{2,3,1} 程序 先给出第一个版本的程序 1 public static void printKNum(int[] source, int k) {//算法入口 2 if (k <= 0) { 3 System.out.println("请出入合法的K值"); 4 } else if (source.length <= k) {//如果数组的长度小于等于K,则全部输出 5

9.7数学与概率(五)——功能:有些数的素数因子只有3、5、7,找出其中第k个数

/** * 功能:有些数的素数因子只有3.5.7,找出其中第k个数. */ 两种方法: 方法一: /** * 思路:将列表中的数字与3,5,7相乘,找出还未加入列表的最小数. * 每次要将Ai加入列表时,就用某个临时列表存放3Ai,5Ai和7Ai.要产生Ai+1时,搜索临时列表,找出最小值. * @param k * @return */ public static int getKthMagicNumger(int k){ if(k<0) return 0; int val=1; Queue

剑指offer (30) 最小的K个数

题目:输入n个整数,找出其中最小的K个数 方法一:直接std::sort,T(n) = O(nlgn) 方法二:直接std::nth_element T(n) = O(n) 但是修改了原数组 void MinKth(std::vector<int>& num, int kth, std::vector<int>& result) { if (num.size() == 0 || || kth <= 0 || kth > num.size()) { thr

剑指Offer面试题30(java版):最小的k个数

题目:输入n个整数,找出其中最小的k个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4 这道题最简单的思路莫过于把输入的n个整数排序,排序之后位于最前面的k个数就是最小的k个数.这种思路的时间复杂度是O(nlogn),面试官会提示我们还有更快的算法. 解法一:O(n)的算法,只有当我们可疑修改输入的数组时可用 从上一题中我们可以得到启发,我们同样可以基于Partition函数来解决这个问题.如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数

算法试题 - 找出最小 k 个数

题目 题目:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 解析 思路1 这一题应用堆排序算法复杂度只有O(nlog k),堆是完全二叉树的一种,最大堆就是最上面的数是最大的该方法基于二叉树或者堆来实现,首先把数组前k个数字构建一个最大堆,然后从第k+1个数字开始遍历数组,如果遍历到的元素小于堆顶的数字,那么久将换两个数字,重新构造堆,继续遍历,最后剩下的堆就是最小的k个数,时间复杂度O(nlog k). 思路2 排序

找出数组中前K小的值&amp;最小堆

题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 代码 public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { if (input.length==0||k>input.length) { return new ArrayList<>(); } ArrayList<Integer> list

面试题-10亿个数中找出最大的10000个数(top K问题)

一个较好的方法:先拿出10000个建立小根堆,对于剩下的元素,如果大于堆顶元素的值,删除堆顶元素,再进行插入操作,否则直接跳过,这样知道所有元素遍历完,堆中的10000个就是最大的10000个.时间复杂度: m + (n-1)logm = O(nlogm) 优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中(如果是字符串hash(x)%M).对每个文件,建立大小为10000的小根堆,然后按有序数组的合并合并起来,取出最大的10000个即是答案. top K问题 在大规模数据

最小的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