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

面试题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

思路一:排序法

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
    	if (k <= 0 || k > nums.size()){
    		return {};
    	}
        sort(arr.begin(), arr.end());
        return vector<int>(arr.begin(), arr.begin() + k);
        /*
        vector<int> ans;
        for (int i=0; i<k; i++){
            ans.push_back(arr[i]);
        }
        return ans;
        */
    }
};
/*48ms,21.1MB*/
/*64ms,21.7MB*/

时间复杂度:O(nlogn)
空间复杂度:O(1)

思路二:multiset最大堆

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        int len = arr.size();
        if (k <= 0 || k > len){
            return {};
        }
        //显式指定最大堆,default is less<int>
        multiset<int, greater<int>> set;
        for (int i=0; i<len; i++){
            if (set.size() < k){
                set.insert(arr[i]);
            } else {
                if (arr[i] < *set.begin()){
                    set.erase(set.begin());
                    set.insert(arr[i]);
                }
            }
        }
        return vector<int>(set.begin(), set.end());
    }
};
/*44ms,26.4MB*/

时间复杂度:O(n)
空间复杂度:O(k)

参考链接:
https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/mian-shi-ti-40-san-chong-jie-fa-pai-xu-multisetzui/

思路:堆

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        if (0 == k) return {};
        priority_queue<int> q;
        for (int i=0; i<k; i++) q.push(arr[i]);
        for (int i=k; i<arr.size(); i++) {
            if (arr[i] < q.top()) {
                q.pop();
                q.push(arr[i]);
            }
        }
        vector<int> ans(k, 0);
        for (int i=k-1; i>=0; i--) {
            ans[i] = q.top();
            q.pop();
        }
        return ans;
    }
};
/*76ms,21.1MB*/

时间复杂度:O(nlogk)
空间复杂度:O(k)

思路:快排

假设划分函数返回的下标是 pos(表示分界值 basic 最终在数组中的位置),即 basic 是数组中第 pos - l + 1 小的数,那么一共会有三种情况:

  1. 如果 pos - l + 1 == k,表示 basic 就是第 k 小的数,直接返回即可;
  2. 如果 pos - l + 1 < k,表示第 k 小的数在 basic 的右侧,因此递归调用 qSort(arr, pos+1, r, k-(pos - l + 1));
  3. 如果 pos - l + 1 > k,表示第 k 小的数在 basic 的左侧,递归调用 qSort(arr, l, pos-1,
    k)。
    参考链接:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zui-xiao-de-kge-shu-by-leetcode-solution/
class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
       qSort(arr, 0, arr.size()-1, k);
       //vector<int> ans(k, 0);
       //for (int i=0; i<k; i++) ans[i] = arr[i];
       //return ans; 
       return vector<int>(arr.begin(), arr.begin() + k);
    }
    void qSort(vector<int>& arr, int l, int r, int k) {
        if (l >= r) return;
        int pos = partition(arr, l, r);
        int num = pos - l + 1;
        if (num == k) return;
        else if (num > k) qSort(arr, l, pos-1, k);
        else qSort(arr, pos+1, r, k-num);

    }
    int partition(vector<int>& arr, int l, int r) {
        int idx = rand() % (r - l + 1) + l;
        swap(arr[idx], arr[r]);
        int basic = arr[r];
        int left = l, right = r;
        while (left < right) {
            while (left < right && arr[left] <= basic) left++;
            while (left < right && arr[right] >= basic) right--;
            if (left < right) swap(arr[left], arr[right]);
        }
        arr[r] = arr[left];
        arr[left] = basic;
        return left;
    }
};
/*40ms,20.1MB*/

时间复杂度:平均复杂度O(n),最坏时间复杂度为O(n*n)
空间复杂度:O(logn)

发布了59 篇原创文章 · 获赞 0 · 访问量 1198

猜你喜欢

转载自blog.csdn.net/u011861832/article/details/104556459