【面试题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. 10 个非常有用的 AngularJS 框架

    AngularJS是最流行的开源web app框架.AngularJS被用于解决阻碍单页应用程序开发的各种挑战. 你作为一个AngularJS用户,却不知道一些可以帮助你美化编码的资源?那么一定不能错 ...

  2. 8套迷人精致的CSS3 3D按钮动画

    1.纯CSS3 3D按钮 按钮酷似牛奶般剔透 CSS3按钮一般都可以设计的非常漂亮,利用投影.渐变等CSS3属性特效可以把按钮渲染的十分动感.今天分享的这款CSS3按钮外观非常特别,它看上去酷似晶莹剔 ...

  3. 9 款赏心悦目的 HTML5/CSS3 特效

    1.HTML5 WebGL实验,超酷的HTML5 Canvas波浪墙 这是一款HTML5 Canvas实验项目,也是波浪特效,只是这不是真正的水波,而是利用柱体高度的变化实现的波浪墙效果. 在线演示 ...

  4. ArcGIS10中matplotlib画图时的中文设置

    利用GIS的数据批量生成XY的图形图像文件,可以直接使用Python.一般大家都是用matplotlib,中文设置的问题参看了许多内容,结论是对错不一,让我折腾了三天,现总结如下: 1.软件的版本.安 ...

  5. html5定位并在百度地图上显示

    在开发移动端 web 或者webapp时,使用百度地图 API 的过程中,经常需要通过手机定位获取当前位置并在地图上居中显示出来,这就需要用到html5的地理定位功能. navigator.geolo ...

  6. C指针赋值

    Node* p = A; Node* f = B; Node* t; t = p; t = f 本人试图让p指向B,但这样操作是不行的.如下图:只是改变了t的指向,p并没有变

  7. 利用二维矩阵求spanning tree

    只做了9个节点的,无权值,使用了n-1个=8个循环,非常麻烦.一级一级判断是否连接,连接及记录所在节点,以后不再使用,确保无回路. 验证后无回路,但只试过几种情况. 代码如下: #include< ...

  8. IOS动画隐式,显式,翻页

    //  ViewController.m //  IOS动画0817 // //  Created by 张艳锋 on 15/8/17. //  Copyright (c) 2015年 张艳锋. Al ...

  9. Ubuntu下MySQL忘记root密码重置

    MySQL忘记root密码肿么办?-_-|||   这种情况虽然不是很常见,但是有时长时间没有登录系统,还真会忘记密码.这时候,如果您能以系统管理员权限登陆密码,那还是有救的.放大招,将其重置即可. ...

  10. shell 字符截取

    Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. # 读sharp 谐音 杀: ${var#*//} 杀掉//左边的,保留右边的 ...