最小的K个数 C++(BFPRT,堆排序)

题目描述

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

//堆排序
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class Solution
{
public:
    void HeapAdjust(vector<int> &a,int s,int n)
    {
        int rc=a[s];
        for(int j=2*s+1; j<=n-1; j=j*2+1)
        {
            if(j<n-1&&a[j]>a[j+1])
                j++;
            if(rc<=a[j])
                break;
            else
            {
                a[s]=a[j];
                s=j;
            }
        }
        a[s]=rc;
    }
    void CreatHeap(vector<int> &a,int n)
    {
        for(int i=n/2-1; i>=0; i--)
        {
            HeapAdjust(a,i,n);
        }
    }
   vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
    {
        vector<int> ans;
        if(input.size()==0||k==0||k>input.size())
            return ans;
        int n=input.size();
        CreatHeap(input,n);
        for(int i=n-1; i>0; i--)
        {
                int x=input[0];
                input[0]=input[i];
                input[i]=x;
                HeapAdjust(input,0,i);
        }
        for(int i=input.size()-1;i>=0&&k>0;i--)
        {
            ans.push_back(input[i]);
            k--;
        }
        return ans;
    }
};
int main()
{
    Solution s;
    int k=4;
    vector<int> ans;
    vector<int> input;
    input.push_back(4);
    input.push_back(5);
    input.push_back(1);
    input.push_back(6);
    input.push_back(2);
    input.push_back(7);
    input.push_back(3);
    input.push_back(8);
    ans=s.GetLeastNumbers_Solution(input,k);
    for(int i=0; i<ans.size(); i++)
    {
        cout<<ans[i];
    }

    return 0;
}
//BFPRT
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> ans;
        if(input.size()==0||k==0||k>input.size())
        {
            return ans;
        }
        for(int i=0; i<=BFPRT(input,0,input.size()-1,k); i++)
        {
            ans.push_back(input[i]);
        }
        return ans;
    }
    /* 插入排序,返回中位数下标 */
    int InsertSort(vector<int> &array, int left, int right)
    {
        int temp;
        int j;
        for (int i = left + 1; i <= right; i++)
        {
            temp = array[i];
            j = i - 1;
            while (j >= left && array[j] > temp)
                array[j + 1] = array[j--];
            array[j + 1] = temp;
        }

        return ((right - left) >> 1) + left;
    }

    /* 返回中位数的中位数下标 */
    int GetPivotIndex(vector<int> &array, int left, int right)
    {
        if (right - left < 5)
            return InsertSort(array, left, right);

        int sub_right = left - 1;
        for (int i = left; i + 4 <= right; i += 5)
        {
            int index = InsertSort(array, i, i + 4);  //找到五个元素的中位数的下标
            swap(array[++sub_right], array[index]);   //依次放在左侧
        }

        return BFPRT(array, left, sub_right, ((sub_right - left + 1) >> 1) + 1);
    }

    /* 利用中位数的中位数的下标进行划分,返回分界线下标 */
    int Partition(vector<int> &array, int left, int right, int pivot_index)
    {
        swap(array[pivot_index], array[right]);  //把基准放置于末尾

        int divide_index = left;  //跟踪划分的分界线
        for (int i = left; i < right; i++)
        {
            if (array[i] < array[right])
                swap(array[divide_index++], array[i]);  //比基准小的都放在左侧
        }

        swap(array[divide_index], array[right]);  //最后把基准换回来
        return divide_index;
    }

    int BFPRT(vector<int> &array, int left, int right, const int & k)
    {
        int pivot_index = GetPivotIndex(array, left, right);            //得到中位数的中位数下标
        int divide_index = Partition(array, left, right, pivot_index);  //进行划分,返回划分边界
        int num = divide_index - left + 1;
        if (num == k)
            return divide_index;
        else if (num > k)
            return BFPRT(array, left, divide_index - 1, k);
        else
            return BFPRT(array, divide_index + 1, right, k - num);
    }
};
int main()
{
    Solution s;
    int k=4;
    vector<int> ans;
    vector<int> input;
    input.push_back(4);
    input.push_back(5);
    input.push_back(1);
    input.push_back(6);
    input.push_back(2);
    input.push_back(7);
    input.push_back(3);
    input.push_back(8);
    ans=s.GetLeastNumbers_Solution(input,k);
    for(int i=0; i<ans.size(); i++)
    {
        cout<<ans[i];
    }

    return 0;
}

原文地址:https://www.cnblogs.com/dshn/p/9426931.html

时间: 2024-08-30 00:47:39

最小的K个数 C++(BFPRT,堆排序)的相关文章

【剑指offer】 堆排序查找最小的K个数

上一篇 说了些堆的建立及其相关操作,这里看下用堆来解决数据量较大的时候,查找最小的k个数的情况.这里会用到上一篇中的函数. 我们先生存1千万个随机数,写到文件中: import random def randData(): with open('randint.txt', 'w') as fd: for i in range(1, 10000000): fd.write('%d ' %random.randint(1, 100)) if i % 100 == 0: fd.write('\r')

找到无序数组中最小的k个数

题目:给定一个无序整数数组arr,找到其中最小的k个数 要求:如果数组arr的长度为n,排序之后自然可以得到最小的k个数,此时时间复杂度与排序的时间复杂度相同均为O(NlogN),本题要求实现时间复杂度为O(NLogK). 1.O(NLogK)的方法,即一直维护一个有k个数的最大的大根堆,这个堆是目前选出的k个最小数,在堆里的k个元素中堆顶的元素是最大的一个. 接下来遍历整个数组,遍历的过程中看当前数是否比堆顶元素小.如果是,就把堆顶的元素替换成当前的数,然后从堆顶的位置调整堆,替换后堆的最大元

找到n中最小的k个数

题目:n个数中,求最小的前k个数. 这道题在各个地方都看到过,在国内出现的频率也非常高. 解法: 1. brute force. O(k*n)复杂度: 2. sort.O(k+n*lgn)复杂度: 3. 最大堆.每次替代的是大小为k的最大堆的最大值.O(k+(n-k)lgk)复杂度. 4. 最小堆.和sort类似,只是建堆后只求前k次.O(n+k*lgn)复杂度.在网上看到一个优化,就是pop出第k小的数(堆顶)的时候,最多只需要调整k-1层(不需要调到堆底).所以可以优化到O(n+k^2).当

算法题:求数组中最小的k个数

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 题目:输入n个整数,找出其中最小的k个数. <剑指offer>给出了两种实现算法: 算法1:采用Partition+递归法,该算法可以说是快速排序和二分查找的有机结合.算法的时间复杂度为O(n),缺点在于在修改Partition的过程中会修改原数组的值. 算法2:采用top-k算法.如果要找最小的K个数,我们才用一个含有K个值的大顶堆:如果要找最大的K个数,我们采用小顶堆.该算法的时间复杂度为O(nlogK),是一种比较好的算法,启发于堆排序

求数组中最小的k个数

题目:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. package test; import java.util.ArrayList; import java.util.Comparator; import java.util.PriorityQueue; import org.junit.Test; public class GetLeastNumbers_Solution { /** * 基于优先队列,时间复杂度为

九度 1371 最小的K个数

题目描述:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 输入: 每个测试案例包括2行:第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度. 第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]. 输出: 对应每个测试案例,输出最小的k个数,并按从小到大顺序打印. 样例输入: 8 4 4 5 1 6 2 7 3 8 样例输出: 1 2 3 4 此题的不同之处是最后的输

编程算法 - 最小的k个数 代码(C)

最小的k个数 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用快速排序(Quick Sort)的方法求解, 把索引值(index)指向前k个数. 代码: /* * main.cpp * * Created on: 2014.6.12 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <stdio.h> #include <stdl

编程算法 - 最小的k个数 红黑树 代码(C++)

最小的k个数 红黑树 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入n个整数, 找出其中的最小k个数. 使用红黑树(multiset), 每次替换最大的值, 依次迭代. 时间复杂度: O(nlogk). 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <iostream> #include <vector> #includ

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