【面试题030】最小的k个数
题目:
    输入n个整数,找出其中最小的k个数。
    例如输入4、5、1、6、2、7、3、8这8个字,则其中最小的4个数字是1、2、3、4。
 
 
思路一:
    可以同样的基于随机快速排序的Partition函数,来对数组做划分,
    基于k来作调整,返回调用Partition函数,直到左边的k个数字是整个数组中最小的k个数字。
    ps.这种方法要修改数组中数字的顺序,因为Partition函数会调整数组中数字的顺序。
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 
#include <iostream>

using namespace std;

void Swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int Partition(int *numbers, int beg, int end)
{
//如果轴是随机取的话,这里得做一个Swap把这个轴元素交换到end位置
    int small = beg - 1;
    int index;
    for (index = beg; index < end; ++index)
    {
        if (numbers[index] <= numbers[end])
        {
            small++;
            Swap(&numbers[small], &numbers[index]);
        }
    }
    ++ small;
    Swap(&numbers[small], &numbers[end]);
    return small;
}

void GetLeastNumbers(int *input, int n, int *output, int k)
{
    if (input == NULL || output == NULL || k > n || n <= 0 || k <= 0)
    {
        return;
    }
    int start = 0;
    int end = n - 1;
    int index = Partition(input, start, end);
    while (index != k - 1)
    {
        if (index > k - 1)
        {
            end = index - 1;
            index = Partition(input, start, end);
        }
        else
        {
            start = index + 1;
            index = Partition(input, start, end);
        }
    }
    for (int i = 0; i < k; ++i)
    {
        output[i] = input[i];
    }

}

int main()
{
    int input[] = {4, 5, 1, 6, 2, 7, 3, 8};
    int output[4];
    int num = sizeof(input) / sizeof(input[0]);
    int k = sizeof(output) / sizeof(output[0]);
    GetLeastNumbers(input, num, output, k);
    for (int i = 0; i < k; ++i)
    {
        cout << output[i] << " ";
    }
    cout << endl;
    return 0;
}

 
 
思路二:
    首先创建一个大小为k的容器来存储最小的k个数字,
    遍历这n个数字,如果容器大小小于k,就放入。如果容器已经满了,则跟容器中的最大数字做比较,
    如果大于最大数字,遍历下一个,如果小于当前已有的最大值,替换当前这个最大值。
    如果用二叉树来实现这个容器,那么我们能在O(logk)
——我想到了最大堆,在O(1)时间内获得已有的k个数字中的最大值,但是需要O(logk)时间完成删除及插入操作。
    我们可以利用红黑树来实现我们的容器,STL中set和multiset都是基于红黑树实现的。
 
 
 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 
#include <iostream>
#include <set>
#include <vector>
using namespace std;

typedef multiset<int, greater<int> > intSet;
typedef multiset<int, greater<int> >::iterator setIterator;

void GetLeastNumbers(const vector<int> &data, intSet &leastNumbers, int k)
{
    leastNumbers.clear();
    if ( k < 1 || (int)data.size() < k )
    {
        return;
    }

vector<int>::const_iterator iter = data.begin();
    for (; iter != data.end(); ++iter)
    {
        //有符号数/无符号数不匹配
        if ((int)(leastNumbers.size()) < k)
        {
            leastNumbers.insert(*iter);
        }
        else
        {
            setIterator iterGreatest = leastNumbers.begin();

if (*iter < * (leastNumbers.begin()))
            {
                leastNumbers.erase(iterGreatest);
                leastNumbers.insert(*iter);
            }
        }
    }
}

int main()
{
    int input[] = {4, 5, 1, 6, 2, 7, 3, 8};
    intSet leastNumbers;
    vector<int> data(&input[0], &input[7]);
    GetLeastNumbers(data, leastNumbers, 4);

while(!leastNumbers.empty())
    {
        setIterator iterGreatest = leastNumbers.begin();
        cout << *iterGreatest << " ";
        leastNumbers.erase(iterGreatest);
    }

cout << endl;
    return 0;
}

 
 

【面试题030】最小的k个数的更多相关文章

  1. 剑指Offer:面试题30——最小的k个数(java实现)

    问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...

  2. 面试题30.最小的k个数

    题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...

  3. 剑指offer 面试题40. 最小的k个数

    O(N)划分法,注意这个方法会改变原数据(函数参数是引用的情况下)!当然也可以再定义一个新容器对其划分 要求前k小的数,只要执行快排划分,每次划分都会把数据分成大小两拨.直到某一次划分的中心点正好在k ...

  4. leetcode 签到 面试题40. 最小的k个数

    题目 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k = ...

  5. 《剑指offer》面试题40. 最小的k个数

    问题描述 输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 示例 1: 输入:arr = [3,2,1], k ...

  6. java实现——030最小的k个数

    1.O(nlogk)海量数据 import java.util.TreeSet; public class T030 { public static void main(String[] args){ ...

  7. 【剑指Offer面试题】 九度OJ1371:最小的K个数

    题目链接地址: http://ac.jobdu.com/problem.php?pid=1371 题目1371:最小的K个数 时间限制:1 秒内存限制:32 兆特殊判题:否提交:5938解决:1265 ...

  8. 面试题40:最小的 k 个数

    import java.util.Arrays; /** * Created by clearbug on 2018/2/26. * * 面试题40:最小的 k 个数 * * 注意:因为前两天在陌陌面 ...

  9. 剑指Offer面试题:27.最小的k个数

    一.题目:最小的k个数 题目:输入n个整数,找出其中最小的k个数.例如输入4.5.1.6.2.7.3.8这8个数字,则最小的4个数字是1.2.3.4. 这道题是典型的TopK问题,其最简单的思路莫过于 ...

随机推荐

  1. 8个3D视觉效果的HTML5动画欣赏

    现在的网页中应用了越来越多的3D应用,特别是基于HTML5 Canvas的动画特效,让用户有一种非常震撼的视觉体验.本文收集了8个非常炫酷的3D视觉效果的HTML5动画,都有源代码分享,你可以学习你感 ...

  2. 生成HTMLTestRunner测试报告的操作步骤——Python+selenium自动化

    HTMLTestRunner是Python标准库的unittest模块的一个扩展,具体操作如下 1.安装 环境:Window8 步骤:1)http://tungwaiyip.info/software ...

  3. zedboard U盘挂载+交叉编译helloworld

    交叉编译环境见http://blog.csdn.net/xiabodan/article/details/22717175 1:编写hello.c文件 #include<stdio.h> ...

  4. 字符串反转(StringBuffer)

    package com.java1234.chap03.sec08; public class zifufanzhuan { public static void main(String[] args ...

  5. php读取excel文件的实例代码

    php读取excel文件的实例代码. 代码: <?php /** * php读取excel文件 * by www.jbxue.com */ $this->loadexcel();//半酣p ...

  6. C# CacheHepler Class

    internal class CacheHelper { /// <summary> /// Insert value into the cache using /// appropria ...

  7. Python开发【第一篇】Python基础之反射

    反射 反射的作用:反射得作用是提高代码可读行. __import__导入模块和import导入模块的区别: __import__导入模块是通过字符串进行导入. import是常用得导入模块方法. 扩展 ...

  8. 无法打开物理文件xxx.mdf 操作系统错误 5:“5(拒绝访问。)” (Microsoft SQL Server,错误: 5120) 的解决方法

    问题描述:在附加数据库到sql server时,附加不上,出现如下图所示的错误 解决方法:找到xxx.mdf和xxx_log.ldf文件, 点击“右键”->“属性”->"安全&q ...

  9. R语言基础(二) 可视化基础

    > which.max(apply(x[c("x1","x2","x3")], 1, sum))49 > x$num[which ...

  10. 使用PHP计算上一个月的今天

    一日,遇到一个问题,求上一个月的今天. 最开始我们使用 strtotime(“-1 month”) 函数求值,发现有一个问题,月长度不一样的月份的计算结果有误. 比如:2011-03-31,得到的结果 ...