1、题目描述
给定整数数组 nums
和整数 k
,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
你必须设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入: [3,2,1,5,6,4],k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4
2、初始思路
2.1 思路1
直接使用sort进行递增排序,直接找到,但忽略了题目中对时间复杂度的要求。sort排序代码的时间复杂度为O(NlogN).
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
nums.sort(reverse = True)
return nums[k-1]

2.2 思路2
看题目属于堆中的定义,了解了堆之后,使用堆的最大堆进行实现。但此时,由于元素的出栈和入栈,时间复杂度仍然不符合要求。
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heap[0]

3 优化算法
3.1 思路
使用分治的方法进行求解,首先随机挑选一个nums中的元素作为基准,根据该基准确定low, equal和high,从而分开进行求解。
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def quickSort(nums, k):
mid = random.choice(nums)
low, equal, high = [], [], []
for num in nums:
if num<mid:
low.append(num)
elif num>mid:
high.append(num)
else:
equal.append(num)
if len(high) >= k:
return quickSort(high, k)
elif len(equal) + len(high) >= k:
return mid
else:
return quickSort(low, k - len(equal) - len(high))
return quickSort(nums, k)

3.2 注意!
刚开始选取元素时,选取了最左侧的元素进行求解,但忽略了如果原数组是按照递增或者递减的顺序进行排列的话,那么每次分治只能去掉一个元素,每次递归处理的数据量:n + (n-1) + (n-2) + ... ≈ n²/2,时间复杂度退化为 O(n²)。
4 总结
当看到复杂度要求为O(N)的排序类型的题时,可以优先考虑能否使用分治发进行求解,二分法也属于分治法的一种。