给定整数数组 nums
和整数 k
,请返回数组中第 k
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
题目来源: 力扣
快速排序
递归部分
当前基准元素的排名
如果不是第K就继续快排,一次排除一半
//快速排序
private int quickSort(int left,int right){
int q=randomPartition(left,right);
//找到第K大即返回
if(q==index){
return a[q];
}else{
return q<index?quickSort(q+1,right):quickSort(left,q-1);
}
}
寻找随机数部分
在范围内随机找一个数,把他换到最右边作为基准
//选择随机位置作为标的
private int randomPartition(int left,int right){
int i=r.nextInt(right-left+1)+left;
// 把标记放在最右边作为标的
swap(right,i);
// 返回标的所在的位置
return partition(left,right);
}
排序部分
最右边为基准,从左到右遍历,小的放在左边,最后把基准放在合适的位置
返回基准位置(排名)
//排序
private int partition(int left,int right){
int x=a[right],i=left;
for(int j=left;j<=right;j++){
if(a[j]<x){
swap(j,i++);
}
}
// 把标的放在适合的位置
swap(right,i);
// 返回标的位置
return i;
}
代码
class Solution {
Random r=new Random();
int index;//目标位置
int l;//数组长度
int[] a;//数组
public int findKthLargest(int[] nums, int k) {
a=nums;
l=nums.length;
index=l-k;
return quickSort(0,l-1);
}
//快速排序
private int quickSort(int left,int right){
int q=randomPartition(left,right);
//找到第K大即返回
if(q==index){
return a[q];
}else{
return q<index?quickSort(q+1,right):quickSort(left,q-1);
}
}
//选择随机位置作为标的
private int randomPartition(int left,int right){
int i=r.nextInt(right-left+1)+left;
// 把标记放在最右边作为标的
swap(right,i);
// 返回标的所在的位置
return partition(left,right);
}
//排序
private int partition(int left,int right){
int x=a[right],i=left;
for(int j=left;j<=right;j++){
if(a[j]<x){
swap(j,i++);
}
}
// 把标的放在适合的位置
swap(right,i);
// 返回标的位置
return i;
}
// 交换
private void swap(int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
海量数据下,面试官更希望你会堆排序
所以这题还可以用最小堆来做
堆排序
主函数
前K个数用上浮操作
后面的数如果比最小堆最小(堆顶)大就替换,并做下沉操作
private int k;
public int findKthLargest(int[] nums, int k) {
this.k = k;
for(int i=0;i<k;i++){
up(nums,i);
}
int n = nums.length;
for(int i=k;i<n;i++){
if(nums[i]>nums[0]){
swap(nums,0,i);
down(nums,0);
}
}
return nums[0];
}
堆的操作
上浮:和父亲比较,如果比父亲小就换
下沉:和儿子比较,和最小的儿子换(如果父亲比它大)
private void up(int[] nums,int index){
if(index==0)return;
int father = (index-1)/2;
if(nums[father]>nums[index]){
swap(nums,father,index);
up(nums,father);
}
}
private void down(int[] nums,int index){
int left=2*index+1,right=left+1,small=index;
if(left<k && nums[left]<nums[small]){
small=left;
}
if(right<k && nums[right]<nums[small]){
small=right;
}
if(small!=index){
swap(nums,small,index);
down(nums,small);
}
}
代码
class Solution {
private int k;
public int findKthLargest(int[] nums, int k) {
this.k = k;
for(int i=0;i<k;i++){
up(nums,i);
}
int n = nums.length;
for(int i=k;i<n;i++){
if(nums[i]>nums[0]){
swap(nums,0,i);
down(nums,0);
}
}
return nums[0];
}
private void up(int[] nums,int index){
if(index==0)return;
int father = (index-1)/2;
if(nums[father]>nums[index]){
swap(nums,father,index);
up(nums,father);
}
}
private void down(int[] nums,int index){
int left=2*index+1,right=left+1,small=index;
if(left<k && nums[left]<nums[small]){
small=left;
}
if(right<k && nums[right]<nums[small]){
small=right;
}
if(small!=index){
swap(nums,small,index);
down(nums,small);
}
}
private void swap(int[] nums,int a,int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
}