【面试题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. javaScript入门2--基本概念

    语法: 1.区分大小写!! 2.标识符:既变量,函数名,属性名,参数. 1.第一个字符必须为字母,_,或者$ 2.其他字符可以是字母,_,&,或者数字 3.注释: 1.单行注释:// 2.多行 ...

  2. Excel 窗体控件属性

    常规 AutoLoad   (Excel) 打开工作簿时是否加载控件.(如果是 ActiveX   控件,则忽略.) Enabled(表单) 控件是否可以接收焦点并响应用户生成的事件. Locked( ...

  3. 关闭MyEclipse代码编辑器(breadcrumb)工具条

    1. 在工具栏上找“Toggle Breadcrumb”按钮,单击使其恢复未选中状态即可 2. 如果找不到这个按钮.通过菜单“Window->Customize Perspective”打开对话 ...

  4. <hash命令:显示、添加或清除哈希表>

    linux系统下的hash指令: 说明:linux系统下会有一个hash表,当你刚开机时这个hash表为空,每当你执行过一条命令时,hash表会记录下这条命令的路径,就相当于缓存一样.第一次执行命令s ...

  5. 伴随ListView、RecyclerView、ScrollView滚动滑入滑出小图标--第三方开源--FloatingActionButton

    FloatingActionButton在github上的项目主页是:https://github.com/makovkastar/FloatingActionButton 它的依赖包NineOldA ...

  6. CLR via C# 混合线程同步构造

    1. 自旋,线程所有权和递归 2. 混合构造 a.ManualResetEventSlim b.SemaphoreSlim c.Monitor d.ReaderWriterLockSlim 3.条件变 ...

  7. andriod

    谷歌提供的安卓源码中,网址如下:http://androidxref.com http://blog.csdn.net/zoe6553/article/details/6622258

  8. <亲测好使>mac os 安装mcrypt扩展

    以前安装opencart的时候倒是不需要mcrypt 这个库.但是新版本需要了.加上自己的 是mac环境.当时闲麻烦,就一直没装.这次下午就寻思给装上吧! 1.首先你要先安装xcode这个工具.不然没 ...

  9. iOS 进阶 第十天(0410)

    0410 在tableViewCell之间添加一根线,通栏 iOS应用数据存储的常用方式 plist存储文件 plist读取文件 下面是plist存储读取的图解: 注意:plist只能存储常见的属性. ...

  10. iOS常见问题(5)

    一.注意将之前storyboard中控制器删除之后,拖入一个新的控制器的时候,stroyboard中控制器的class也要重新填入自己想要展示的控制器,告诉stroyboard去加载哪个控制器. 二. ...