1. 原始题目
在未排序的数组中找到第 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 ≤ 数组的长度。
2. 思路
可以利用优先队列存储元素,然后分别出对,每次出对都是最大元素,那么第k次出队时就是第k大元素了。然而此题本意并非在此。比较好的解法是利用快排中的partition操作!因为对于每次partition操作,都可以确定第m大的元素。如果是从小到大排列的数组,那么如果m>k,则应该在右子区间继续partition操作。如果m<k则应该在左子区间继续partition操作。如果m==k,则说明找到了,直接返回即可。
举例如下:
【42,46,67,3,34,7,66,21】将首元素进行partition后:【3,34,7,21,42,46,67,66】,此时m=4,如果找第k=4大的元素,那么正好找到了,直接返回即可。如找k=2的元素66,则应该继续在子区间【m+1:】来搜索,否则在【:m】区间搜索。
3. 解题
1 def paitition(arr,left,right): # pritition 快排核心思想:在v的左边元素都小于v,v右边元素都大于v
2 if not arr: return None
3 temp = arr
4 arr = arr[left:right]
5
6 v = arr[0] # 取第一个元素作为pivot元素
7 j = 0 # [l+1,j]>v [j+1,i)>v
8 for i in range(len(arr)):
9 if arr[i]<v: # 当前元素小于v则交换
10 arr[j+1],arr[i] = arr[i],arr[j+1]
11 j=j+1
12 arr[0],arr[j] = arr[j],arr[0] # 最后将该首位元素pivot交换到合理位置
13 temp[left:right] = arr
14 return temp,left+j
15
16
17 class Solution:
18 def findKthLargest(self, nums, k):
19 if not nums:return None
20 left,right = 0,len(nums)
21 while True:
22 num, pos = paitition(nums,left,right)
23 if len(nums)-pos==k:
24 return nums[pos]
25 elif len(nums)-pos>k:
26 left = pos+1
27 else:
28 right = pos+1