如果对整个数组进行排序的话,前 个元素就是最小的 个数,但这样做时间成本就比较高了。
我们来介绍一下这道题目的两种比较优秀的解法。一种是利用了快排的部分思路,另一种利用了堆排的部分思路。
先介绍一下快排相关的解法。利用快排的partition函数来进行划分。如果我们的基准数划分完成了以后在第 位上的话,那基准数以及基准数前面的元素就是最小的 个数了。
class Solution { public: //快排思路 int partition(vector<int>&arr,int l,int r) { int x = arr[l]; while( l < r ) { while(l < r && arr[r] >= x) { r--;} arr[l] = arr[r]; while(l < r && arr[l] < x) { l++;} arr[r] = arr[l]; } arr[l] = x; return l; } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; int n = input.size(); if(k > n ||k<=0){return ans;} int l = 0; int r = n-1; int mid = partition(input,l,r); while(mid != k-1) { if(mid > k-1) { r = mid-1; mid = partition(input,l,r); } else{ l = mid+1; mid = partition(input,l,r); } } for(int i = 0 ; i < k ; i++) { ans.push_back(input[i]); } return ans; } };
这个题目可以借助数据结构堆在 的时间复杂度完成。并且不会修改原数组,特别适合处理海量的数据且k比较小的时候来进行。下面我们来介绍一下做法。
创建一个大根堆,限定其最多只能放 个元素。然后依次取待排序的数据 往堆里放,堆没满的话直接插入就可以了。如果堆满了的话,那目前堆顶元素就是堆中的最大值。这个时候我们来比较一下 和堆顶元素的大小。如果 比堆顶元素大的话,那就说明数据中已经有 个元素比 小了。 已经不可能属于最小的 个数了。那就直接忽略掉 继续看下一个数。如果 比堆顶元素小的话,那就将堆顶元素删除,把 插入到堆中。
堆在C++中的优先队列底层就是用堆实现的。Java和python中也可以使用优先队列。这样的话,我们直接利用优先队列就可以实现的时间复杂度获取堆顶元素,的复杂度进行插入和删除了
class Solution { public: vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans ; int N = input.size(); if(k > N||k==0){return ans;} priority_queue<int> heap; for(int i = 0 ; i < N ; i++) { if(i < k){heap.push(input[i]);} else{ if(heap.top() > input[i]) { heap.pop(); heap.push(input[i]); } } } while(!heap.empty()) { ans.push_back(heap.top()); heap.pop(); } return ans; } };
下面再附上一份手写堆的代码。
class Solution { public: //堆排思路(手写堆 int heapSize;//记录堆的大小 int Left(int i){ if(i*2+1>=heapSize) return -1; return i*2+1; } int Right(int i){ if(i*2+2>=heapSize) return -1; return i*2+2; } void minHeapify(vector<int> & heap,int i) { int L = Left(i); int R = Right(i); int maxi = i; if(L != -1 && heap[L]>heap[i]){ maxi = L;} if(R != -1 && heap[R]>heap[maxi]){ maxi = R;} if(maxi != i){ swap(heap[i],heap[maxi]); i = maxi; minHeapify(heap,i); } } void Delete(vector<int> & heap) { swap(heap[heapSize-1],heap[0]); heapSize--; minHeapify(heap,0); } void Insert(vector<int> & heap,int n) { heap[heapSize] = n; int i = heapSize; heapSize++; while(i!=0&& heap[i]>heap[(i-1)/2]) { swap(heap[i],heap[(i-1)/2]); i = (i-1)/2; } } vector<int> GetLeastNumbers_Solution(vector<int> input, int k) { vector<int> ans; int n = input.size(); if(k>n || k<=0 ){return ans;} heapSize = 0; vector<int> heap(k); for(int i = 0 ; i < n ; i++) { if(heapSize < k) {Insert(heap,input[i]);} else{ if(heap[0] > input[i]){ Delete(heap); Insert(heap,input[i]); } } } return heap; } };