leetcode215数组中的第K个最大元素
快排简介
快排即为快速排序算法,其的速度是相较于其他排序算法最快的
快排的思想
- 每次在区间中选择一个pivot,也就是作为分界点
- 将小于它的放它的左边,将大于它的分到它的右边
- 如果区间的l和r相等则返回
快排代码
public static void quickSort(int l,int r){
if(r==l)return;
int mid=arr[(l+r)/2];
int i=l-1;
int j=r+1;
while(i<j){
while(arr[++i]<mid){}
while(arr[--j]>mid){}
if(i<j){
int t=arr[i];
arr[i]=arr[j];
arr[j]=t;
}
}
quickSort(l,j);
quickSort(j+1,r);
}
快排题目
更近一步:215. 数组中的第K个最大元素 - 力扣(LeetCode)
这里主要详细讲的就是更近一步的题目:
关键点:需要时间复杂度为:O(n),也就是我们使用原生的快排进行排序后是会超时的
所以我们需要改变思路:
快排的时间复杂度为O(nlogn)这个logn是由于我们分为两个部分后两个部分都要处理,如果只负责一个部分即可
那么我们的解决思路如下:
我们在一次快排时,总能确定下pivot的位置,那么我们就根据当前pivot的位置是否符合nums.length-k,来划分
值得一提的是:我们模板题的划分是
quickSort(l,j);
quickSort(j+1,r);
那么我们这个j是否就意味着对应的pivot分配后的位置呢?以及如果他是的话?我们是不是直接返回就好了?
首先j并不是pivot分配后的值,理由如下:
- 在while流程内我们pivot第一个会进行更改位置,如果正常进行更改位置,且会再次进入到while中,那么j是会直接跳过上次把pivot换到的j这个位置的所以基本上不可行
所以我们不能采取这样的措施,那么我们怎么利用这个快排来得到我们的答案呢?
其实这个过程有点类似二分的思想,在我们while后被分成了两批,也就是左部分,以及右部分,在这之中,我们的左部分符合的条件是<pivot,而右部分是大于pivot的,所以我们通过dfs来相当于二分这个区间,且第k大的元素必然存在,当区间缩减为只有一个元素时,则为最终的答案
代码部分
class Solution {
public int findKthLargest(int[] nums, int k) {
//快排秒了
return quickSort(nums,nums.length-k,0,nums.length-1);
}
public int quickSort(int []nums,int k,int l,int r){
//我们只划分两边然后在剩下的两个区间中只会接着处理其中一个
//如果<=k,那么处理>k的那段,否则处理>k的那段
if(r==l)return nums[k];
int p=nums[l];
int i=l-1;
int j=r+1;
while(i<j){
while(nums[++i]<p){}
while(nums[--j]>p){}
if(i<j){
int t=nums[j];
nums[j]=nums[i];
nums[i]=t;
}
}
if(j>=k){
return quickSort(nums,k,l,j);
}else{
return quickSort(nums,k,j+1,r);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误