leetcode面试题40. 最小的k个数

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

示例 1:

输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

示例 2:

输入:arr = [0,1,2,1], k = 1
输出:[0] 

限制:

0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000

完整代码

借助此题,顺便复习下排序算法
快排
开始时,flag这里出了问题,应该是记录最左端的这个数本身,写成了记录其下标
下面是将数组快排后,返回前K 个元素(其实不用)

class Solution {
     
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
     
        if(k < 1)
            return vector<int> ();
        fast_sort(arr, 0, arr.size() - 1);
        vector<int> res(k);
        for(int i = 0; i < k; ++i)
            res[i] = arr[i];
        
        return res;
    }
private:
    void fast_sort(vector<int>& arr, int left, int right){
     
        
        if(left >= right)
            return;
        int flag = arr[left];
        int l = left, r = right;
        while(l < r){
     
            while(l < r && arr[r] >= flag)
                --r;
            arr[l] = arr[r];
            while(l < r && arr[l] < flag)
                ++l;
            arr[r] = arr[l];
        }
        arr[l] = flag;
        fast_sort(arr, left, l - 1);
        fast_sort(arr, l + 1, right);
    }
};

(星标思想)借助快排,找到数组中的第K小的元素,该元素左面的就是结果
注意:像寻找数组中的第k小元素,都用快速选择来处理,类似于快排

class Solution {
     
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
     
        if(k < 1)
            return vector<int> ();
        partition(arr, 0, arr.size() - 1, k - 1);//注意这里是下标k-1
        vector<int> res(k);
        for(int i = 0; i < k; ++i)
            res[i] = arr[i];
        
        return res;
    }
private:
    void partition(vector<int>& arr, int left, int right, int k){
     
        int p = fast_sort(arr, left, right);
        if(p == k)//此时前k个元素是前k小的元素
            return;
        else if(p > k){
     //说明第k小的元素在[left, p)
            partition(arr, left, p - 1, k);            
        }
        else{
     //说明第k小的元素在(p,right]
            partition(arr, p + 1, right, k);
        }
    }
    int fast_sort(vector<int>& arr, int left, int right){
            
        
        int flag = arr[left];
        int l = left, r = right;
        while(l < r){
     
            while(l < r && arr[r] >= flag)
                --r;
            arr[l] = arr[r];
            while(l < r && arr[l] < flag)
                ++l;
            arr[r] = arr[l];
        }
        arr[l] = flag;
        return l;
    }
};

归并排序
结果:超时了,通过了33/38

class Solution {
     
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
     
        if(k < 1)
            return vector<int> ();
        vector<int> temp(arr);
        merge_sort(arr, temp, 0, arr.size() - 1);
        vector<int> res(k);
        for(int i = 0; i < k; ++i)
            res[i] = arr[i];
        
        return res;
    }
private:
    void merge_sort(vector<int>& arr, vector<int> temp, int left, int right){
            
        
        if(left >= right)
            return;
        int mid = (left + right) >> 1;
        merge_sort(arr, temp, left, mid);
        merge_sort(arr, temp, mid + 1, right);
        
        int i = mid, j = right, k = right;
        while(i >= left && j >= mid + 1){
     
            if(arr[i] > arr[j]){
     
                temp[k--] = arr[i--];
            }
            else{
     
                temp[k--] = arr[j--];
            }
        }
        while(i >= left){
     
            temp[k--] = arr[i--];
        }
        while(j >= mid + 1){
     
            temp[k--] = arr[j--];
        }
        
        ++k;
        while(k <= right){
     
            arr[k] = temp[k];
            ++k;
        }
        
    }
};

借助大根堆
默认情况下,c++中的priority_queue是大根堆实现的,也就是队列中的元素是降序排列的

class Solution {
     
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
     
        if(k < 1)
            return vector<int> ();
        vector<int> res;
        priority_queue<int> q;
        //1.先将前k个元素入队
        for(int i = 0; i < k; ++i){
     
            q.push(arr[i]);
        }
        //2.判断后续的元素,如果小于队头元素,则将队头元素更新为该元素
        for(; k < arr.size(); ++k){
     
            if(arr[k] < q.top()){
     
                q.pop();
                q.push(arr[k]);
            }
        }
        //3.将队列中的元素存入vector
        while(!q.empty()){
     
            res.push_back(q.top());
            q.pop();
        }
        return res;
    }
};

你可能感兴趣的:(c++,#,算法)