数组中的第K个最大元素题目的思路探讨与源码
数组中的第K个最大元素的题目如下图,该题属于数组和排序类型的题目,主要考察对于数组和排序的使用和理解。本文的题目作者想到2种方法,分别是二分法和小顶堆方法,其中二分法使用java进行编写,而堆排序方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
本人认为该题目可以使用二分法,首先把数组上下限值确定好,然后开始进行遍历,计算出中间值,然后用中间值去寻调用计算方法。在该方法内部是传入一个数组和中间值,遍历数组,只要有数组元素的值比中间值大,那么就计数并加1,最终返回计数值。调用完方法之后,拿返回值和k比较,是否超过了k。如果超过了,则将中值赋予区间的下限值,也就是说整个数组的元素有至少K个都比中值要大,必须将搜索范围的下限移动到中值;如果没有超过K,则将中值赋予区间的上限值,也就是说整个数组的元素有没有K个比中值大的元素,必须将搜索范围的上限移动到中值减去1的位置。然后遍历完毕后再调用计数方法进行比较,如果比K大就返回右侧值,如果比K小就返回左侧值。那么按照这个思路我们的Java代码如下:
#喷火龙与水箭龟
class Solution {
public int findKthLargest(int[] nums, int k) {
int smallNum=-10000;
int bigNum=10000;
while(smallNum<bigNum-1){
int inNum=smallNum+(bigNum-smallNum)/2;
int pq=countFun(nums,inNum);
if(pq>=k){
smallNum=inNum;
} else {
bigNum=inNum-1;
}
}
if(countFun(nums,bigNum)>=k){
return bigNum;
}
else{
return smallNum;
}
}
private int countFun(int nums[], int ind) {
int kr=0;
for(int ir:nums){
if(ir>=ind){
kr=kr+1;
}
}
return kr;
}
}
显然,我们还可以使用小顶堆的方法进行处理,首先初始化一个空列表,然后计算原始数组的长度,遍历从0到k-1的元素,将数组的元素放入小顶堆,然后开始从k开始遍历,把列表第一个元素记为堆顶元素,只要数组里的元素比堆顶元素大,就替换堆顶元素,最后返回堆顶元素即可。所以根据这个思路就可以写出代码,下面是Python代码部分:
#喷火龙与水箭龟
from typing import List
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
ls=[]
nums_len=len(nums)
for ij in range(k):
heapq.heappush(ls,nums[ij])
for jr in range(k,nums_len):
flag=ls[0]
if(nums[jr]>flag):
heapq.heapreplace(ls,nums[jr])
return ls[0]
从结果来说java版本的二分法的速度不错,但是python版本的堆排序方法的速度比较一般,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。