/*
描述
给定一个数组,找出其中最小的K个数。例如数组元素是4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
0 <= k <= input.length <= 10000
0 <= input[i] <= 10000
Main idea:
最好的方法是使用大小为k的大项堆,遍历数组的每个元素,若该元素小于堆顶,则替换堆顶并进行percolate down(时间复杂度为log k),维持大项堆。
最终返回该大项堆即可,总的时间复杂度为:O(nlog(k))
此处用vector代替大项堆,每次替换堆顶后进行sort最简单,此时总的时间复杂度为:O(n* klog(k)),当n足够大时,性能是要比直接sort原数组:O(nlog(n))要好的
Note:
每次替换堆顶后进行插入排序也简单,此时时间复杂度为: O(n
k)
*/

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;


class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        // O(n* k*log(k))
        if (k > input.size() || k == 0)
            return vector<int>{};
        vector<int> hp(input.begin(), input.begin() + k);
        sort(hp.begin(), hp.end());
        for (int i = k; i < input.size(); ++i) {
            if (input[i] < hp[k - 1]) {
                hp[k - 1] = input[i];
                sort(hp.begin(), hp.end());
            }
        }
        return hp;
    }

    vector<int> GetLeastNumbers_Solution_1(vector<int> input, int k) {
        // O(n*k)
        if (k > input.size() || k == 0)
            return vector<int>{};
        vector<int> hp(input.begin(), input.begin() + k);
        int i, j;
        sort(hp.begin(), hp.end());
        for (i = k; i < input.size(); ++i) {
            if (input[i] < hp[k - 1]) {
                hp[k - 1] = input[i];
                for (j = k - 2; j >= 0; j--) {
                    if (hp[j] > input[i]) {
                        hp[j + 1] = hp[j];
                        continue;
                    }
                    hp[j + 1] = input[i];
                    break;
                }
                if (j < 0)
                    hp[0] = input[i];

            }
        }
        return hp;
    }

    vector<int> GetLeastNumbers_Solution_2(vector<int> input, int k) {
        // O(nlog(n))
        sort(input.begin(), input.end());
        return k <= input.size() ? vector<int>(input.begin(), input.begin() + k) : vector<int>{};
    }
};