【剑指offer】40、最小的K个数

题目

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

思路一

基于partition,当 index正好为k的时候,就是第k大的数。时间复杂度O(n)

缺点:需要改变数组

class Solution {
public:
    int Partition(vector<int>& input, int begin, int end)
    {
        int low = begin, high = end;
        int pivot = input[low];
         
        while(low < high)
        {
            while( low < high && pivot<=input[high])
            {
                high--;
            }
            input[low] = input[high];
            while(low < high && pivot >= input[low])
            {
                low++;
            }
            input[high] = input[low];
        }
        input[low] = pivot;
        return low;
    }
     
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len=input.size();
        if(len == 0 || k > len || k <= 0)
            return vector<int>();
        if(len == k) 
            return input;
         
        int start = 0, end = len - 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);
            }
        }
         
        vector<int> res(input.begin(), input.begin() + k);
        return res;
    }
};

思路二

使用最大堆,存储最小的k个数字,时间复杂度为O(nlogk)。

当插入时,若该元素比容器中最大元素小,则把该元素放入。

优点:不需要更改数组,适合海量数据

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
    {
        vector<int> result;
        int len = input.size();
        if(input.empty() || k <= 0 || len < k)
            return result;
          
        multiset<int, greater<int>> leastNumbers; // 从大到小排序
        multiset<int, greater<int>>::iterator iterGreater; // 定义迭代器
          
        vector<int>::iterator iter = input.begin();
        for(; iter != input.end(); ++iter)
        {
            // 将前k个数直接插入进multiset中,注意是小于K
            if (leastNumbers.size() < k)
                leastNumbers.insert(*iter);
            else
            {
                // 因为设置的从大到小排序,故multiset中第一个位置的元素即为最大值
                iterGreater = leastNumbers.begin();
                  
                // 如果input中当前元素比multiset中最大元素小,则替换;即保持multiset中这k个元素是最小的。
                if(*iter < *(leastNumbers.begin()))
                {
                    // 替换掉当前最大值
                    leastNumbers.erase(iterGreater);
                    leastNumbers.insert(*iter);
                }
            }
        }
          
        for(iterGreater = leastNumbers.begin(); iterGreater!=leastNumbers.end(); ++iterGreater)
            result.push_back(*iterGreater); // 将multiset中这k个元素输出
        
        return result;
    }
};

猜你喜欢

转载自www.cnblogs.com/shiganquan/p/9344759.html