
找第K大元素
暴力解法:排序后取第K个
时间复杂度:O(nlogn)O(n \log n)O(nlogn),取决于排序算法(如快排、归并排序)
空间复杂度:O(1)O(1)O(1) 或 O(n)O(n)O(n),取决于排序实现
python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
nums.sort() # 暴力排序
print(nums) # 从小到大
return nums[-k]
快速选择(Quick Select)算法
平均时间复杂度:O(n)
- 每次划分大约把数组分成两半,递归只进入一边。
- 平均递归深度约为 log n,但每层只处理部分数组,所以平均时间复杂度是 O(n)。
最坏情况:O(n²)(但可通过随机化 pivot 避免)
空间复杂度:O(1)(原地修改数组)
class中自己调自己,用self.
python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
# 快速选择(数组在无序状态下,每次抛一半: O(n))(二分法是有序状态下每次抛一半 O(log n))
# 1. 随机选择一个分组参考值
center = nums[-1]
# 2. 分成3个部分
left = [x for x in nums if x > center] # 值大于center的
mid = [x for x in nums if x == center] # 值 = center的
right = [x for x in nums if x < center] # 值 < center的
# 3. 判断 第k大 所在部分
if k <= len(left): # 值大于center的个数,超过k个,说明k在左边
return self.findKthLargest(left,k) # class中自己调自己,用self.
elif k <= len(left)+ len(mid): # 第k大的值就=center值,而且可能还有好几个相同值
return center
else: # 在右边
return self.findKthLargest(right, k-len(left)-len(mid))