最小的k个数

来源:互联网 发布:南山软件产业基地图片 编辑:程序博客网 时间:2024/06/06 13:04

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

题解

1. 全排序

直接sort函数,返回前k个
时间复杂度O(nlogn)

2. 冒泡或选择排序

时间复杂度O(k*n)

class Solution {public:    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {        vector<int> haha;        if(k > input.size())    return haha;        for(int i = 0; i < k; i++){            for(int j = i + 1; j < input.size(); j++){                if(input[i] > input[j]) swap(input[i], input[j]);            }            haha.push_back(input[i]);        }        return haha;    }};

3. 堆排序

维护容量为k的最大堆

  1. 用容量为k的最大堆存储最先遍历到的k个数,同样假设它们即是最小的k个数
  2. 遍历剩余n-k个数。假设每一次遍历到的新的元素的值为x,把x与堆顶元素kmax比较:如果x < kmax,用x替换kmax,然后更新堆(用时logk);否则不更新堆。
    时间复杂度:O(k+(n-k)*logk)=O(n*logk)
class Solution {public:    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {        int len = input.size();        if(len <= 0 || k <= 0 || k > len)   return vector<int>();        vector<int> haha(input.begin(), input.begin() + k);        makeHeap(haha);        for(int i = k; i < len; i++){            if(input[i] < haha[0]){                haha[0] = input[i];                adjustHeap(haha, 0);            }        }        return haha;    }private:    void adjustHeap(vector<int>& input, int i){        int len = input.size();        if(i > len / 2 - 1) return; //叶节点        int left = 2 * i + 1, right = left + 1;        int max = i;        if(left < len && input[max] < input[left])  max = left;        if(right < len && input[max] < input[right])    max = right;        if(max != i){            swap(input[max], input[i]);            adjustHeap(input, max);           }    }    void makeHeap(vector<int>& input){        for(int i = input.size() / 2 - 1; i >= 0; i--){            adjustHeap(input, i);        }    }};

4. 快排思想

  1. 选取S中一个元素作为枢纽元v,将集合S-{v}分割成S1和S2,就像快速排序那样
  2. 如果k <= |S1|,那么第k个最小元素必然在S1中,返回QuickSelect(S1, k)。
  3. 如果k = 1 + |S1|,那么枢纽元素就是第k个最小元素,即找到,直接返回它。
  4. 否则,这第k个最小元素就在S2中,即S2中的第(k - |S1| - 1)个最小元素,我们递归调用并返回QuickSelect(S2, k - |S1| - 1)。
class Solution {public:    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {        vector<int> haha;        if(k > input.size())    return haha;        QuickSelect(input, 0, input.size() - 1, k);        for(int i = 0; i < k; i++){            haha.push_back(input[i]);        }        return haha;    }private:    void QuickSelect(vector<int>& input, int left, int right, int k){        if(k <= 0 || left + k > right)  return;        int pivot = (left + right) >> 1;        swap(input[left], input[pivot]);        //注意特殊用例,如(1,2),i应指向1        int i = left, j = right;        while(i < j){            //先让j走保证i指向不大于pivot的值            while(i < j && input[j] > input[left])  j--;            while(i < j && input[i] <= input[left]) i++;            if(i < j){                swap(input[i], input[j]);            }        }        swap(input[left], input[i]);        QuickSelect(input, i + 1, right, k - i - 1 + left);        QuickSelect(input, left, i - 1, k); //用i-1而不是i,防止如(1,1,1)的死循环    }};
0 0