题目列表
-
215. 数组中的第K个最大元素 中等难度 leetcode链接
-
347. 前K个高频元素 中等难度 leetcode链接
-
295. 数据流的中位数 困难难度 leetcode链接
题目
(1)数组中的第K个最大元素
题目
给定整数数组 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
提示:
-
1 <= k <= nums.length <= 10(5) -
-10(4) <= nums[i] <= 10(4)
思路
可以采用快排、堆排序实现
如下是堆排序实现:
# 时间复杂度:O(n+klogn)。其中 n 为数组的长度,k 为要求的第k大数的k值。初始化建堆的时间复杂度为 O(n),建完堆以后每次调整(即max_heapify)的时间复杂度为 O(logn),需要 k 次调整,因此总时间复杂度为 O(n+klogn)。
# 空间复杂度:O(1),原地(inplace)排序可认为无额外空间开销。
# 链接:https://leetcode.cn/problems/kth-largest-element-in-an-array/solutions/1507044/by-flix-amc8/
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def max_heapify(arr, i, end): # 大顶堆
j = 2*i + 1 # j为i的左子节点【建堆时下标0表示堆顶】
while j <= end: # 自上而下进行调整
if j+1 <= end and arr[j+1] > arr[j]: # i的左右子节点分别为j和j+1
j += 1 # 取两者之间的较大者
if arr[i] < arr[j]: # 若i指示的元素小于其子节点中的较大者
arr[i], arr[j] = arr[j], arr[i] # 交换i和j的元素,并继续往下判断
i = j # 往下走:i调整为其子节点j
j = 2*i + 1 # j调整为i的左子节点
else: # 否则,结束调整
break
n = len(nums)
# 建堆【大顶堆】
for i in range(n//2-1, -1, -1): # 从第一个非叶子节点n//2-1开始依次往上进行建堆的调整
max_heapify(nums, i, n-1)
# 排序:依次将堆顶元素(当前最大值)放置到尾部,并调整堆
# k-1次重建堆(堆顶元素),或 k次交换到尾部(倒数第k个元素)
for j in range(n-1, n-k-1, -1):
nums[0], nums[j] = nums[j], nums[0] # 堆顶元素(当前最大值)放置到尾部j
max_heapify(nums, 0, j-1) # j-1变成尾部,并从堆顶0开始调整堆
return nums[-k]
(2)前K个高频元素
题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
-
1 <= nums.length <= 10(5) -
k的取值范围是[1, 数组中不相同的元素的个数] -
题目数据保证答案唯一,换句话说,数组中前
k个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(nlog n) ,其中 n 是数组大小。
思路
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
#要统计元素出现频率
map_ = {} #nums[i]:对应出现的次数
for i in range(len(nums)):
map_[nums[i]] = map_.get(nums[i], 0) + 1
#对频率排序
#定义一个小顶堆,大小为k
pri_que = [] #小顶堆
#用固定大小为k的小顶堆,扫描所有频率的数值
for key, freq in map_.items():
heapq.heappush(pri_que, (freq, key))
if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
heapq.heappop(pri_que)
#找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
result = [0] * k
for i in range(k-1, -1, -1):
result[i] = heapq.heappop(pri_que)[1]
return result
(3)数据流的中位数
题目
中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
-
例如
arr = [2,3,4]的中位数是3。 -
例如
arr = [2,3]的中位数是(2 + 3) / 2 = 2.5。
实现 MedianFinder 类:
-
MedianFinder()初始化MedianFinder对象。 -
void addNum(int num)将数据流中的整数num添加到数据结构中。 -
double findMedian()返回到目前为止所有元素的中位数。与实际答案相差10(-5)以内的答案将被接受。
示例 1:
输入 ["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"] [[], [1], [2], [], [3], []]
输出 [null, null, null, 1.5, null, 2.0]
解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1); // arr = [1]
medianFinder.addNum(2); // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3); // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0
提示:
-
-10(5) <= num <= 10(5) -
在调用
findMedian之前,数据结构中至少有一个元素 -
最多
5 * 10(4)次调用addNum和findMedian
思路
from heapq import *
class MedianFinder:
def __init__(self):
self.A = [] # 小顶堆,保存较大的一半
self.B = [] # 大顶堆,保存较小的一半
def addNum(self, num: int) -> None:
if len(self.A) != len(self.B):
heappush(self.B, -heappushpop(self.A, num))
else:
heappush(self.A, -heappushpop(self.B, -num))
def findMedian(self) -> float:
return self.A[0] if len(self.A) != len(self.B) else (self.A[0] - self.B[0]) / 2.0
# 题解:https://leetcode.cn/problems/find-median-from-data-stream/solutions/2361972/295-shu-ju-liu-de-zhong-wei-shu-dui-qing-gmdo/
# 时间复杂度 O(logN) :
## 查找中位数 O(1) : 获取堆顶元素使用 O(1) 时间。
## 添加数字 O(logN) : 堆的插入和弹出操作使用 O(logN) 时间。
# 空间复杂度 O(N) : 其中 N 为数据流中的元素数量,小顶堆 A 和大顶堆 B 最多同时保存 N 个元素。
结尾
亲爱的读者朋友:感谢您在繁忙中驻足阅读本期内容!您的到来是对我们最大的支持❤️
正如古语所言:"当局者迷,旁观者清"。您独到的见解与客观评价,恰似一盏明灯💡,能帮助我们照亮内容盲区,让未来的创作更加贴近您的需求。
若此文给您带来启发或收获,不妨通过以下方式为彼此搭建一座桥梁: ✨ 点击右上角【点赞】图标,让好内容被更多人看见 ✨ 滑动屏幕【收藏】本篇,便于随时查阅回味 ✨ 在评论区留下您的真知灼见,让我们共同碰撞思维的火花
我始终秉持匠心精神,以键盘为犁铧深耕知识沃土💻,用每一次敲击传递专业价值,不断优化内容呈现形式,力求为您打造沉浸式的阅读盛宴📚。
有任何疑问或建议?评论区就是我们的连心桥!您的每一条留言我都将认真研读,并在24小时内回复解答📝。
愿我们携手同行,在知识的雨林中茁壮成长🌳,共享思想绽放的甘甜果实。下期相遇时,期待看到您智慧的评论与闪亮的点赞身影✨!
万分感谢🙏🙏您的点赞👍👍、收藏⭐🌟、评论💬🗯️、关注❤️💚
自我介绍:一线互联网大厂资深算法研发(工作6年+),4年以上招聘面试官经验(一二面面试官,面试候选人400+),深谙岗位专业知识、技能雷达图,已累计辅导15+求职者顺利入职大中型互联网公司。熟练掌握大模型、NLP、搜索、推荐、数据挖掘算法和优化,提供面试辅导、专业知识入门到进阶辅导等定制化需求等服务,助力您顺利完成学习和求职之旅(有需要者可私信联系)
友友们,自己的知乎账号为“快乐星球”,定期更新技术文章,敬请关注!

413

被折叠的 条评论
为什么被折叠?



