题意描述:
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
示例:
示例一:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例二:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
解题思路:
Alice: 这题倒是有点意思了。
Bob: 怎么说,很难吗?
Alice: 不是很难,但是会有很多种做法。寻找一个未排序数组中的第 K 大的元素。可以直接排个序然后返回指定的值。这种最快也要O(n * log n)
。
Bob: 也可以维护一个最大堆
,先把所有元素都放进去,然后从堆顶取出 K
个元素,最后一个取出的就是第 K
大的元素。
Alice: 最大堆会比直接排序更快吗 ?
Bob: 额,应该不会。不过也是一种解法了。
Alice: 还有一种,把冒泡排序
用进来。还记得吗,冒泡排序可以每趟将一个最大或者最小的元素冒到 数组的末尾, 我们只要重复 K
趟就能在 length-K
的位置找到 第 K
大的元素了。
Bob: 哟,不错不错。
代码:
Python 方法一: 排序 + 返回指定位置元素
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
nums.sort()
return nums[-k]
Java 方法一: 排序 + 返回指定位置的元素
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
//System.out.println(nums[0]);
return nums[nums.length-k];
}
}
Python 方法二:冒泡排序 => 超时
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
for x in range(k):
for z in range(0, len(nums)-1):
if nums[z] > nums[z+1]:
nums[z], nums[z+1] = nums[z+1], nums[z]
return nums[-k]
Java 方法二: 冒泡排序,顺利通过。
class Solution {
public int findKthLargest(int[] nums, int k) {
int tmp = 0;
for(int i=0; i<k; ++i){
for(int j=0; j<nums.length-1; ++j){
if(nums[j] > nums[j+1]){
tmp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = tmp;
}
}
}
return nums[nums.length - k];
}
}
Python 方法三: 使用 heapq
模块构建最大堆。
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
# heapq.nlargest()方法返回列表中最大的若干个数组成的子列表。
# 其有两个参数,k 为最大的前k个数,nums 为传入的列表。
return heapq.nlargest(k, nums)[-1]
Java 方法三: 使用优先队列 PriorityQueue
实现大顶堆。
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue <Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>(){
public int compare(Integer a, Integer b){
return a-b;
}
});
for(int num: nums){
maxHeap.add(num);
}
while(maxHeap.size() > k){
maxHeap.poll();
}
return maxHeap.poll();
}
}
易错点:
[3,2,1,5,6,4]
2
[3,2,3,1,2,4,5,5,6]
4
[1,0,2]
1
[1]
1
5
4
2
1
总结: