【Leetcode Top-K问题 BFPRT】第三大的数(414)
题目
给定一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。要求算法时间复杂度必须是O(n)。
示例 1:
输入: [3, 2, 1]
输出: 1
解释: 第三大的数是 1.
示例 2:
输入: [1, 2]
输出: 2
解释: 第三大的数不存在, 所以返回最大的数 2 .
示例 3:
输入: [2, 2, 3, 1]
输出: 1
解释: 注意,要求返回第三大的数,是指第三大且唯一出现的数。存在两个值为2的数,它们都排第二。
解答
思路:
1,题目要求时间复杂度必须是O(n),那么排序肯定是不行了,由于只是求第三大,那么可以先求出第一大,再求出第二大,再求第三大,总的时间复杂度O(N)。
2,BFPRT,专门解决TOP-K问题,但是因为序列中可能有重复值,所以在进行BFPRT之前,先去重,总的时间复杂度O(N)。
(2020.1.7更)
3,堆,大小为k的小顶堆,k=3。Time: N·log(k) = O(N), Space: O(1)
4,二叉排序树,首先构建一颗二叉排序树,中序遍历得出从小到大的序列,取第K大。构建二叉排序树平均log(N),最差O(N),查找第K大O(N)
5,AVL树,优化的二叉排序树,优化了构建二叉树的时间复杂度,最差log(N),中序遍历查找第K大O(N)
通过代码如下:
方法一
class Solution:
def thirdMax(self, nums: List[int]) -> int:
l = list(set(nums))
max_list = []
sum = min(3, len(l))
while sum:
max = -float('inf') # 负无穷
for x in l:
if x > max and x not in max_list:
max = x
if max not in max_list:
# l.remove(max) remove时间复杂度为O(n)
del l[l.index(max)]
max_list.append(max)
sum -= 1
return max_list[-1] if len(max_list)>=3 else max_list[0]
BFPRT
class Solution:
def thirdMax(self, nums) -> int:
k = 3 # 代表求第三大
nums = list(set(nums))
if len(nums) < 3:
return max(nums)
def getmedian(lis):
"""返回序列lis中位数,在BFPRT中就是求每5个数小组的中位数"""
begin = 0
end = len(lis) - 1
sum = begin + end
mid = sum // 2 + sum % 2 # 这个地方加上sum%2是为了确保偶数个数时我们求的是中间两个数的后一个
return sorted(lis)[mid]
def BFPRT(nums, left, right):
"""分成每5个数一个小组,并求出每个小组内的中位数"""
num = right - left + 1
offset = 0 if num % 5 == 0 else 1 # 最后如果剩余的数不足5个,我们也将其分成一个小组,和前面同等对待
groups = num // 5 + offset
median = [] # 中位数数组
for i in range(groups):
begin = left + i * 5
end = begin + 4
Median = getmedian(nums[begin:min(end, right) + 1])
median.append(Median)
return getmedian(median)
def partition(nums, left, right, base):
"""在 nums[left, right] 将基准base归位"""
temp = nums[base]
nums[base], nums[right] = nums[right], nums[base] # 基准和末尾元素互换
max_index = left
for i in range(left, right): # 把所有小于基准的移到左边
if nums[i] <= temp: # 要等于啊!这里好坑的说.. 否则通不过[3, 3, 3, 3, 4, 3, 3, 3, 3] k = 1
nums[max_index], nums[i] = nums[i], nums[max_index]
max_index += 1
nums[right], nums[max_index] = nums[max_index], nums[right] # 基准归位
return max_index
def select(nums, left, right, k_smallest):
"""在 nums[left, right] 找第k小的元素"""
if left == right: # 递归终止条件
return nums[left]
# pivot_index = random.randint(left, right)
base = BFPRT(nums, left, right)
base_index = partition(nums, left, right, nums.index(base)) # 选base为基准,并归位。
if base_index == k_smallest: # 判断目前已归位的基准,是不是第k_smallest位
return nums[k_smallest]
elif k_smallest < base_index: # 递归左半部分
return select(nums, left, base_index - 1, k_smallest)
else: # 递归右半部分
return select(nums, base_index + 1, right, k_smallest)
return select(nums, 0, len(nums) - 1, len(nums)-k) # 第k大,是第n-k小
【Leetcode Top-K问题 BFPRT】第三大的数(414)的更多相关文章
- [LeetCode] Top K Frequent Elements 前K个高频元素
Given a non-empty array of integers, return the k most frequent elements. For example,Given [1,1,1,2 ...
- LeetCode "Top K Frequent Elements"
A typical solution is heap based - "top K". Complexity is O(nlgk). typedef pair<int, un ...
- [LeetCode] Top K Frequent Words 前K个高频词
Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...
- Top K问题-BFPRT算法、Parition算法
BFPRT算法原理 在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为pivot,而在BFPTR算法中,每次选择五分 ...
- LeetCode - Top K Frequent Words
Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...
- 数组中的第K个最大元素leetcode(Top K的问题)
在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...
- LeetCode 第三大的数414. Third Maximum Number
题目 描述:给定数组中求第三大的数字:如果没有,返回最大的:时间复杂度O(n) 记得<剑指offer>才看到过这样的求第k大的题目.但是忘记具体怎么做了.只好先自己想了. 因为时间复杂度的 ...
- Top K Frequent Elements 前K个高频元素
Top K Frequent Elements 347. Top K Frequent Elements [LeetCode] Top K Frequent Elements 前K个高频元素
- LeetCode 414. 第三大的数(Third Maximum Number) 3
414. 第三大的数 414. Third Maximum Number 题目描述 给定一个非空数组,返回此数组中第三大的数.如果不存在,则返回数组中最大的数.要求算法时间复杂度必须是 O(n). 每 ...
- C#版(打败99.28%的提交) - Leetcode 347. Top K Frequent Elements - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
随机推荐
- bzoj1706 relays 奶牛接力跑 线性代数
题目描述 FJ的N(2 <= N <= 1,000,000)头奶牛选择了接力跑作为她们的日常锻炼项目.至于进行接力跑的地点 自然是在牧场中现有的T(2 <= T <= 100) ...
- 【python之路45】tornado的用法 (三)
参考:https://www.cnblogs.com/sunshuhai/articles/6253815.html 一.cookie用法补充 1.cookie的应用场景 浏览器端保存的键值对,每次访 ...
- Django项目:CRM(客户关系管理系统)--59--49PerfectCRM实现CRM客户报名流程学生合同表单验证
# sales_views.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.db import IntegrityError #主动捕 ...
- 巧用 position:absolute
1.跟随性 下面这种方法更加简便以及更方便维护, 例如“西部世界”,由于不用将父元素设为position:relative,position:absolute的位置也就不用根据文字多少而重新进行top ...
- 关于Cesium 官方教程
最近一直在准备第一次QQ群的Cesium基础培训公开课,虽说使用Cesium也有段日子了,但是要说对Cesium了解有多深,还真不一定.原因是一直以来我都是用哪里学哪里.基于多年开发三维数字地球的底层 ...
- Activiti实战04_简单流程
在Activiti实战03_Hello World中我们介绍了一个中间没有任何任务的流程,实现了流程的部署与查阅,而在本章中,将会为流程添加任务节点,是流程能够像个流程,变得更加丰满起来. 在上一节的 ...
- webService cxf学习
1.首先去官网下载cxf包 http://archive.apache.org/dist/cxf/ 记住要选.zip结尾 大概40兆的样子 2.把上边的包都放项目里.如果你用的jeecg框架,那它自带 ...
- Tensorflow技巧
1.尽量控制图片大小在1024以内,不然显存会爆炸. 2.尽量使用多GPU并行工作,训练下降速度快. 3.当需要被检测的单张图片里物体太多时,记得修改Region_proposals的个数 4.测试的 ...
- TZ_08_maven私服项目的上传和下载
1. 需求 正式开发,不同的项目组开发不同的工程. ssm_dao工程开发完毕,发布到私服. 2下载 nexus Nexus 是 Maven 仓库管理器,通过 nexus 可以搭建 maven 仓 ...
- VSCode 配置阿里云CentOS 7.6 远程开发
配置步骤 一.windows 10 开发机配置 windows 10 1809后支持ssh命令 1.生成ssh密钥.使用以下命令,先生成本地公钥和私钥ssh-keygen -t rsa -b 4096 ...