【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 ...
随机推荐
- 关于Canvas的坐标系
注意Canvas的坐标系应该是这样子的: 看下面的例子: 最后的显示效果是:
- 19-10-24-H
H H H H H H ZJ一下: T1只会暴力,测试点分治. (表示作者的部分分并没有给够,暴力加部分表按测试点分类可以得60吧……) T2先直接手玩第一个子任务. 然后就$Find$了一个神奇的( ...
- struts1 总结吧
以前都是使用struts2,但是新公司要使用struts1,所有只有硬着头皮上了. 一.Dynamic Method Invoc : 自定义的 Action 必须继承 DispatchAction 而 ...
- C#可扩展编程之MEF(一):MEF简介及简单的Demo
在文章开始之前,首先简单介绍一下什么是MEF,MEF,全称Managed Extensibility Framework(托管可扩展框架).单从名字我们不难发现:MEF是专门致力于解决扩展性问题的 ...
- 原 JEECMS导入IDEA进行二次开发图文教程
JEECMS导入IDEA进行二次开发图文教程 2017年05月15日 17:03:53 Swain_Ho 阅读数 3257 版权声明:本文为博主原创文章,未经博主允许不得转载. https:// ...
- Flask中cookie和session设置与csrf原理攻防
Flask之操作cookie app.py from flask import Flask, request, Response app = Flask(__name__) @app.route('/ ...
- shell中各种括号的作用详解()、(())、[]、[[]]、{}
一.小括号,圆括号() 1.单小括号 () ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号, ...
- 啊啊我找不到web.xml怎么办呀~~
创建Dymamic Web Project的时候不要忘记勾选这玩意(about servlet) 其实还有一个办法就是右键点击你的web项目名--->Java EE Tools-->Gen ...
- Octave 软件的安装
每次安装软件都感觉是一种心痛的历程.下载安装,然后就跳出一堆的错误,之后就各种百度求救,然后就搞了大半天,有时候还搞不定. 最后,搞定的时候发现,原来这么简单,结果时间就这样浪费了,所以还是把这个过程 ...
- 20190902+0903合集-NOIP模拟
一直没时间写QwQ 于是补一下. Day 1 晚饭吃的有点恶心…… $1s\,2s\,5s$ 还开 -O2 ?? 有点恐怖. T1 猛的一想: 把外面设成一个点, 向入口连一条权为排队时间的边 从出口 ...