选取TOP K的问题之快速排序
Posted xuan01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了选取TOP K的问题之快速排序相关的知识,希望对你有一定的参考价值。
- 问题:选取数组中最小的前k个数,见剑指 Offer 40. 最小的 k 个数(基于快速排序的数组划分,清晰图解) - 最小的k个数 - 力扣(LeetCode)
方法1:快速排序:
- 哨兵划分:选取一个哨兵,将大于哨兵的移到哨兵右侧;小于哨兵的移到哨兵左侧。
- 递归操作:递归的将左右子数组进行哨兵划分,直至区间长度为1,完成递归。
- 快排完成后将数组前k个值输出
void quicksort(vector<int>&arr,int l,int r) if(r<=1) return; int i = l;int j = r; while(i<j) while(i<j && arr[j] >= arr[l]) --j; while(i<j && arr[i] <= arr[l]) ++i; swap(arr[i],arr[j]); swap(arr[l],arr[i]); quicksort(arr,l,i-1); quicksort(arr,i+1,r);
l和r是数组的左右边界;
时间复杂度:O(Nlog N); 空间复杂度:O(log N)最好;O(N)最坏
方法2:基于快速排序的数组划分
核心思想:因为返回的值不要求排序,只需要找出最小的前k个值就行。所以不再对左右两个子数组都进行递归操作,而是根据 k的值 与每次递归之后的 i值进行比较,若大于i,则说明前 第 k+1 个最小值在右子数组,小于i,则说明 第k+1个最小值在左子数组,若相等,则说明是 arr[k]即为第k+1个最小值,直接返回前k个值。
class public: vector<int> getLeastNumbers(vector<int>&arr,int k) if(k>=arr.size()) return arr; return quicksort(arr,k,0,arr.size()-1); private: vector<int> quicksort(vector<int>& arr,int k,int l ,int r) int i = l, j = r; while(i<j) while(i<j && arr[j] >= arr[l]) --j; while(i<j && arr[i] <= arr[l]) ++i; swap(arr[i],arr[j]); swap(arr[i],arr[l]); if(k > i) return quicksort(arr,k,i+1,r); if(k < i) return quicksort(arr,k,l,i-1); vector<int>v; v.assign(arr.begin(),arr.begin()+k); return v; ;
时间复杂度:等比数列求和,O(N); 空间复杂度:O(log N)。
以上是关于选取TOP K的问题之快速排序的主要内容,如果未能解决你的问题,请参考以下文章
Top K Frequent Elements 之 topk问题