在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
这一题可能是高频考题吧!涉及到快速排序和堆排序。
针对本题,第一想法:先从大到小排序,然后取第K个值。我掌握最熟练的冒泡排序,但是它的时间复杂度太高了,为O(n^2),运行完了提示时间超出了限制。
解法一:快速排序
思想:分而治之。设立一个基准值pivot,通过一趟排序后,大于pivot的放在右边,小于pivot的数放在左边。对左右两边分别递归排序,直至整个数组排好序。时间复杂度O(nlogn),空间复杂度O(logn)(递归使用栈的空间代价)
class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: def quicksort(arr,l,r): if l>=r: return arr pivot = arr[l] low = l high = r while(l<r): while(l<r and arr[r]>=pivot): r = r-1 arr[l] = arr[r] while(l<r and arr[l]<=pivot): l = l+1 arr[r] = arr[l] arr[l] = pivot quicksort(arr,low,l-1) quicksort(arr,l+1,high) quicksort(nums,0,len(nums)-1) return nums[len(nums)-k]
解法二:快速选择排序
在快速排序的基础上,可以进一步改进为快速选择排序。即判断较大值排序好的序列长度是否为K,如果为K,直接返回;如果小于K,则继续对左子序进行排序;如果大于K,则对右子序进行排序即可。
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
low,high = 0,len(nums)-1
def quicksort(arr,l,r):
if l>=r:
return l
pivot = arr[l]
low = l
high = r
while(l<r):
while(l<r and arr[r]>=pivot):
r = r-1
arr[l] = arr[r]
while(l<r and arr[l]<=pivot):
l = l+1
arr[r] = arr[l]
arr[l] = pivot
return l
while True:
l = quicksort(nums,low,high)
if len(nums)-l == k:
return nums[l]
elif len(nums)-l<k:
high = l-1
else:
low = l+1
解法三:堆排序
对于一个堆(Heap)来说,1.完全二叉树2.所有父节点都大于(或小于)子节点。一定要从上到下,从左到右依次添加。
分为大顶堆(升序排列)(父节点大于两个子节点)和小顶堆 (降序排列)。平均时间复杂度O(nlogn)。空间复杂度是O(logn)。
对于一个完全二叉树,节点标号为i,那么父节点标号为(i-1)/2,向下取整;左子节点标号为2i+1,右子节点为2i+2
从最后一个节点的父节点开始heapify,首先将整个二叉树进行堆化,然后交换根节点和最后一个节点,取出最后一个节点,对新的二叉树进行堆化。
有个博主视频讲解堆排序很清晰:https://www.bilibili.com/video/BV1Eb41147dK/?spm_id_from=333.788.recommend_more_video.-1
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def swap(arr,i,j):
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
def heapify(arr,n,i):
c1 = 2*i+1
c2 = 2*i+2
max = i
if c1<n and arr[c1]>arr[max]:
max = c1
if c2<n and arr[c2]>arr[max]:
max = c2
if i!=max:
swap(arr,i,max)
heapify(arr,n,max)
def build_heap(arr,n):
last_node = n-1
parent = int((last_node-1)/2)
for i in range(parent,-1,-1):
heapify(arr,n,i)
def heap_sort(arr,n):
build_heap(arr,n)
for i in range(n-1,-1,-1):
swap(arr,i,0)
heapify(arr,i,0)
heap_sort(nums,len(nums))
return nums[len(nums)-k]