原题:点击此处
考点:
TopK:即前最大k个数或前最小k个数
最大堆,最小堆
快排
这道题非常考验综合能力
思路一:
使用内置排序工具,进行排序,这个做法不明智。
时间复杂度O(nlogn)
空间复杂度O(1)
思路二:(比较好实现)
使用最大堆,来维持一个k大小的的堆。(手动实现一个堆也是不现实的,也要用内置工具函数,即PriorityQueue)
时间复杂度O(nlogk)
空间复杂度O(k)
优点:不用改变数组
思路三:(比较高效)
利用快排的思想,将数组patition为k前和k后
时间复杂度是O(n),最坏的情况是O(n2)
空间复杂度是O(n2)
缺点:会改变数组
思路二
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(k == 0){
return new int[0];
}
int[] ans = new int[k];
PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>(){
public int compare(Integer num1,Integer num2){
return num2 - num1;
}
});
for(int i = 0; i < k;i++){
queue.offer(arr[i]);
}
for(int i = k; i<arr.length; i++){
if(queue.peek() > arr[i]){
queue.poll();
queue.offer(arr[i]);
}
}
for(int i = 0;i<k;i++){
ans[i] = queue.poll();
}
return ans;
}
}
思路三
class Solution {
public int[] getLeastNumbers(int[] arr, int k) {
if(k == 0){
return new int[0];
}
quickSortForTopK(arr,0,arr.length-1,k);
int[] ans = new int[k];
for(int i = 0; i< k;i++){
ans[i] = arr[i];
}
return ans;
}
public void quickSortForTopK(int[] arr,int left,int right,int k){
if(left >= right){
return;
}
int index = patition(arr,left,right);
int num = index-left+1;
if(num == k){
return;
}
if(num > k){
quickSortForTopK(arr,left,index-1,k);
}else{
quickSortForTopK(arr,index+1,right,k-num);
}
}
public int patition(int[] arr,int left,int right){
Random random = new Random();
int rnum = random.nextInt(right-left+1)+left;
swap(arr,left,rnum);
int pivot = arr[left];
int le = left;
for(int i = left+1; i<= right; i++){
if( arr[i] <= pivot ){
le++;
swap(arr,i,le);
}
}
swap(arr,left,le);
return le;
}
public void swap(int[] arr,int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}