手撕算法系列——2. top-k问题

本文介绍了四种解决top-k问题的算法,包括简单的排序、逐步剔除最大元素、最小堆实现和基于快速排序划分思想的二分法。重点讲解了最小堆和BFPRT算法的原理和时间复杂度,提供了C语言的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    这道题也是很经典的面试题了,因为很多互联网公司要处理海量数据,从海量数据中筛选第k大(小)的数据成为了很常见的问题,这道题也因为解法众多而一直受到热议。下面假定问题是要从n个不同大小的数据寻找第k大的元素,即有k-1个元素大于它。

(1)解法一——简单粗暴排序

    这个解法不用多说了,如果使用基于比较的排序,则平均时间复杂度为O(nlogn),如果n很大的话,这个时间复杂度是难以接受的,而且问题只需要寻找k个最大的元素,而这个解法将所有元素排序了一遍,相当不划算。

(2)解法二——每次剔除一个最大的元素,直至第k个

    这个解法也很容易实现,寻找数组中最大的元素的时间复杂度是线性的,因此这个算法的时间复杂度为O(nk),如果k<<n,这个算法的时间复杂度已经大大优于解法一了,但是如果k也很大,这个算法还是相当消耗时间的。

(3)解法三——用最小堆实现

    top-k问题可以理解为寻找k个最大的元素里面最小的一个,因此可以利用堆的性质,即最小堆的root结点的data域是堆中最小的。先建立一个结点数固定为k的最小堆,遍历整个数组的元素,将其与堆的根节点值进行比较,如果遇到比根节点值更大的元素,则更新根节点值为该值,并将堆重新排序;如果遇到的值比根节点值小,则直接pass掉。这样遍历完整个数组后,根节点的值便是第k大的值了。这个算法的可视化执行过程可以在Ben Frederickson的个人博客中找到,很形象。

    由于堆重排的时间复杂度为O(logk),因此整个算法的时间复杂度为O(nlogk),比解法二优化了不少,并且这个解法的优点不仅可以找到第k大的元素,还能找出前k大的k个元素。

    C语言实现:

/*
### 关于华为技术面试的准备资料与经验 #### 技术面试的核心考点 华为的技术面试通常会围绕几个核心领域展开,包括但不限于据结构、算法设计、编程能力以及具体技术栈的知识点。这些内容可以通过刷 LeetCode 上的经典题目来提升解题速度和准确性[^1]。此外,在实际面试过程中,可能会被要求代码并解释逻辑,因此熟练掌握常见的算法模式(如动态规划、回溯法等)至关重要。 #### 面试流程概述 整个面试流程一般分为多个环节,首先是简历筛选阶段,应聘者需确保个人简历清晰展示其技术实力与过往项目经历,并尽量贴合所申请职位的要求[^2]。随后进入上机考试部分,此轮考察候选人解决实际编码问题的能力;接着可能是行为类评估——即性格测试,它基于心理学理论帮助HR判断求职者的适配度。最后则是正式的一对一或多对一面谈,期间除了探讨专业技术外还会涉及职业发展规划等方面的话题。 #### 实际案例分析 一位成功获得录用通知的候选人在描述自己参加7月19日那场面试的经历时表示:“当时先给了一道有关堆栈操作的应用场景模拟练习让我当场完成。”尽管该挑战属于基础层面但依然考验了他对基本概念的理解程度及其快速反应力。“之后便深入挖掘了我的某些既往工程实例”,这一步骤旨在验证声明的真实性同时也提供了进一步交流的机会以便更全面地认识对方。“至于框架相关的常识问答则占据了剩余时间的头。” #### 推荐学习资源链接 为了更好地备战此类选拔活动,《Java面试题全》由小林Coding网站提供了一份详尽清单可供参考[^3] 。另外还可以参照历年积累下来的经验帖作为辅助工具书使用,比如有篇文档记录了一个真实用户的完整历程就很有借鉴意义[^4]. ```python def stack_operations(): """简单演示进出栈的操作""" from collections import deque stack = deque() # 入栈 stack.append('A') stack.append('B') print(f"After push operations: {list(stack)}") # 出栈 top_element = stack.pop() if stack else None print(f"Popped element: {top_element}, Remaining Stack:{list(stack)}") stack_operations() ``` 以上脚本片段展示了如何利用Python标准库中的`deque`实现简单的压入弹出动作,这是理解抽象据类型的良好开端之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值