问题描述:
数组中的第K个最大元素
在未排序的数组中找到第 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次就结束(堆排序属于选择排序)。
Python3实现:
# @Time :2018/6/26
# @Author :LiuYinxing
# 解题思路 大根堆
class Solution:
def sift(self, nums, low, high):
i, j = low, 2 * low # nums[j] 是 nums[i]的左孩子
tmp = nums[i]
while j <= high:
if j < high and nums[j] < nums[j + 1]: # 若右孩子较大,把 j 指向右孩子
j += 1
if tmp < nums[j]:
nums[i] = nums[j] # 将 nums[j] 调整到双亲节点的位置上
i = j # 修改 i 和 j 值,以便继续向下筛选
j = 2 * i
else: break # 筛选结束
nums[i] = tmp # 被筛选节点的值放入最终位置
def findKthLargest(self, nums, k):
n = len(nums)
for i in range(n//2, -1, -1): # 循环建立初始堆
self.sift(nums, i, n-1)
for i in range(n-1, n-1-k, -1): # 进行排序,每一趟堆排序的元素个数减1
nums[i], nums[0] = nums[0], nums[i] # 将最后一个元素同当前区间内 nums[0] 对换
self.sift(nums, 0, i - 1)
return nums[i]
if __name__ == '__main__':
nums, k = [3, 2, 3, 1, 2, 4, 5, 5, 6], 4
solu = Solution()
print(solu.findKthLargest(nums, k))
Python自带库实现:
# @Time :2018/6/26
# @Author :LiuYinxing
# 解题思路 大根堆
import heapq
class Solution:
def findKthLargest(self, nums, k):
return heapq.nlargest(k, nums)[-1]
if __name__ == '__main__':
nums, k = [3, 2, 3, 1, 2, 4, 5, 5, 6], 4
solu = Solution()
print(solu.findKthLargest(nums, k))
Python heapq模块常用函数复习:
heapq.heappush(heap, item) 把item添加到heap中(heap是一个列表)
heapq.heappop(heap) 把堆顶元素弹出,返回的就是堆顶
heapq.heappushpop(heap, item) 先把item加入到堆中,然后再pop,比 heappush() 再 heappop() 要快得多
heapq.heapreplace(heap, item) 先pop,然后再把item加入到堆中,比 heappop() 再 heappush() 要快得多
heapq.heapify(x) 将列表x进行堆调整,默认的是小顶堆
heapq.merge(*iterables) 将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器
heapq.nlargest(n, iterable, key=None) 返回最大的n个元素,是个列表 list(Top-K问题)
heapq.nsmallest(n, iterable, key=None) 返回最小的n个元素,是个列表 list(Top-K问题)