剑指Offer-30-最小的k个数

来源:互联网 发布:java编写计算器源代码 编辑:程序博客网 时间:2024/04/29 05:06

题目:
输入n个整数,找出其中最小的k个数。例如输入4,5,1,6,2,7,3,8,则最小的4个数字是4,1,2,3.
思路1:使用Partition函数的O(n)算法
可以基于Partition函数来解决这个问题。如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数字大的所有数字都位于数组的右边。这样调整之后,位于数组中左边的k个数字就是最小的k 个数字(这k 个数字不一定是排序的〉。

#include <iostream>using namespace std;//调用Partition(a,low,high)时,对a[low..high]做划分,//并返回基准记录的位置int Partition(int a[], int low, int high) {    //以第一个元素作为基准值    //比pivot值小的元素放在数组的左边,比pivot值大的元素放在数组右边    int pivot = a[low];    //从区间两端交替向中间扫描,直至low=high为止    while (low < high) {        while (low < high && a[high] >= pivot)//pivot相当于在位置low上            high--;//从右向左扫描,查找第1个关键字小于pivot.key的记录a[high]        if (low < high)//表示找到的a[high]的关键字<pivot            a[low++]=a[high];//相当于交换a[low]和a[high],交换后low指针加1        while (low < high && a[low] <= pivot)//pivot相当于在位置high上            low++;//从左向右扫描,查找第1个关键字大于pivot.key的记录a[low]        if (low < high)//表示找到的a[low]的关键字>pivot            a[high--]=a[low];//相当于交换a[low]和a[high],交换后high指针减1    }    a[low] = pivot;    //基准记录已被最后定位    return low;}void print(int a[], int length) {    for (int i = 0; i < length; i++)        cout << a[i] << " ";    cout << endl;}void MinK(int* a,int length,int* min,int k) {    if (a == NULL || length <= 0 || min == NULL || k <= 0 || k>length)        return;    int low = 0,high = length-1;    int index = Partition(a,low,high);    while(index != k-1) {        if(index > k-1) {            high = index-1;            index = Partition(a,low,high);        }        else {            low = index+1;            index = Partition(a,low,high);        }    }    for(int i=0;i<k;i++)        min[i] = a[i];}int main() {    int data[] = {4, 5, 1, 6, 2, 7, 3, 8};    int expected1[4],expected2[8],expected3[1];    MinK(data,8,expected1,4);    MinK(data,8,expected2,8);    MinK(data,8,expected3,1);    print(expected1,4);    print(expected2,8);    print(expected3,1);    return 0;}
0 0
原创粉丝点击