最小的k个数

1,问题:

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

2,想法:

(1),直接排序,然后选取前k个最小的数,时间o(nlogn)

(2),采用冒泡排序的思想,最外层for循环为k,时间复杂度为O(kn)

(3),采用快速排序中Partition的方法,找到第k大数字的位置,然后输出前k个数字。时间o(n)

但是这三种方法都要改变原数组的内容,且如果数据量过大而不能一次性存放在内存时就不合适了。

(4),利用STL中的容器set和multiset,它们都是基于红黑树实现的,能够在logn的时间内实现查找,插入和删除,自动以升序排序。

若以我们只需要在内存中维持一个大小为k的set容器,以降序排列。那么当前容器的最大值肯定在begin()上,再从原数组中取一个数,若大于当前set的最大值就放弃,若小于则替换。扫描一遍即可。时间复杂度为o(nlogk)。

3,编码:

class Solution {
public:
    //下边是利用partition的思想
    /*int Partition(vector<int> &input, int length, int start, int end)
    {
        int pivot = input[start];//枢轴
        int i = start;
        int j = end;
        while (i < j)
        {
            //找到第一个比pivot小的数
            while (i < j && input[j] >= pivot)j--;
            //交换
            if (i < j)input[i] = input[j];
            //找到第一个比pivot大的数
            i = i + 1;
            while (i < j && input[i] <= pivot)i++;
            if (i < j)input[j] = input[i];
            j = j - 1;    
        }
        input[i] = pivot;
        return i;
    }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> vec;
        if (input.empty() || k ==0 || k > input.size())
        {
            return vec;
        }
        if (k == input.size())
        {
            return input;
        }
        //找到第k大的数字
        int length = input.size();
        int start = 0;
        int end = length - 1;
        int index = Partition(input, length, start, end);
        while (index != k - 1)
        {
            if (index > k - 1)
            {
               end = index - 1;
               Partition(input, length, start, end);
            }
            else
            {
                start = index + 1;
                Partition(input, length, start, end);
            }         
        }
        for (int i = 0; i <= index; i++)
        {
            vec.push_back(input[i]);
        }
        return vec;
    }
    */
    typedef multiset<int, greater<int>> intset;//把multiset的默认升序变为降序排列
    typedef multiset<int, greater<int>>::iterator setiterator;
    
     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
         //这里是利用排序的思想
          /*vector<int> vec;
          if (input.size() == 0 || k == 0 || k > input.size())
          {
              return vec;
          }
          //sort(input.begin(), input.end());
          //partial_sort(input.begin(), input.begin() + k, input.end());
          nth_element(input.begin(), input.begin() + k - 1, input.end());
          for (int i = 0; i < k; i++)
          {
              vec.push_back(input[i]);
          }
          return vec;
          */
         //这里是利用红黑树实现的容器set来实现n很大k很小的情况
         vector<int> vec;
         intset leastnumber;
         if (input.size() == 0 || k == 0 || k > input.size())
         {
             return vec;
         }
         for (int i = 0; i < input.size(); i++)
         {
             if (leastnumber.size() < k)
             {
                 leastnumber.insert(input[i]);
             }
             else
             {
                 setiterator itergreatest = leastnumber.begin();
                 if (input[i] < *leastnumber.begin())
                 {
                     leastnumber.erase(itergreatest);
                     leastnumber.insert(input[i]);
                 }
             }
         }
         setiterator it = leastnumber.begin();
         for (; it != leastnumber.end(); it++)
         {
             vec.push_back(*it);
         }
         return vec;
      }
      
};
学习一下怎么使用容器set和multiset。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值