import heapq
import random
'''
如果比赛的时候要使用堆
自己写肯定不现实
当然是要那人家的用
但是python自带的没有大根堆
所以这里就用负数使用小根堆
'''
'''
首先这种写法很快很快,大概是o(logn)级别的
基本思路:
如果说将一组数据(不包含负数)对半分
一半是小的,一半是大的
小的不管里面是怎么弄得,最大的可以拿到
大的不管里面是怎么弄得,最小的可以拿到
我又是对半分的,是不是可以取出中位数?
怎么弄呢?
拿两个堆,一个大根堆,一个小根堆
第一个元素进入大根堆中
开始下一个元素如果比大根堆堆顶元素小,放在大根堆中
比大根堆堆顶元素大,放在小根堆中
为了保证是一半一半的
每当|大根堆.size-小根堆.size|>=2时,将多的那个出堆,放入少的
'''
class dui():
def __init__(self):
pass
def heappush(self,nums,item):
#首先获得插入item对应的i
i=len(nums)
#将item放入堆中
nums.append(item)
#为了满足堆的性质现在进行比较,上移
while i//2>=1: #确保进来的时候,还在堆里面
#对应根节点下标
if nums[i//2]<nums[i]:
#交换位置
nums[i//2],nums[i]=nums[i],nums[i//2]
else:
#能进来说明item要大一些,或相等,这时候就不需要循环了
break
i=i//2
def heappop(self,nums):
#这是优化之后的出对代码
#删除尾部元素:
pop_value=nums.pop()
#突然想到我可能想见一下根节点是哪一个
root=nums[1]
#替换根节点
nums[1]=pop_value
#获得列表下标最大值
max_len=len(nums)-1
i=1
#开始循环,下沉
while 2*i<=max_len:
'''无子节点,不需要进行操作'''
'''需要操作的就是只有左子节点,和两个子节点都有的情况'''
#子节点最小值
min=self.min(nums,i,max_len)
if nums[i]>=nums[min]:
return root
else:
nums[i],nums[min]=nums[min],nums[i]
i=min
return root
def min(self,nums,i,max_len):
#我需要用到这个函数一定是只有左子节点和两个子节点都有的情况
if 2*i+1>max_len:
#只有左子节点
return 2*i
else:
if nums[2*i]<nums[2*i+1]:
return 2*i+1
else:
return 2*i
def fun1(nums):
if nums==[]:
return 0
xiao_dui=[]
da_dui=[0]
duixiang = dui()
da_dui.append(nums[0])
for i in range(1,len(nums)):
cur=nums[i]
if cur>da_dui[1]:
heapq.heappush(xiao_dui,cur)
else:
duixiang.heappush(da_dui,cur)
if len(da_dui)-len(xiao_dui)>=3:
#将大堆出来放在小堆里面
item=duixiang.heappop(da_dui)
heapq.heappush(xiao_dui,item)
elif len(xiao_dui)-len(da_dui)>=1:
#将小堆出来放在大堆里面
item = heapq.heappop(xiao_dui)
duixiang.heappush(da_dui, item)
if len(da_dui)-1==len(xiao_dui):
return (da_dui[1]+xiao_dui[0])/2
if len(da_dui)-1>len(xiao_dui):
return da_dui[1]
return xiao_dui[0]
def fun2(arr):
if arr==[]:
return 0
mid=len(arr)//2
if len(arr)%2==0:
return (arr[mid-1]+arr[mid])/2
else:
return arr[mid]
def main():
for i in range(15):
arr1 = suiji()
arr2 = arr1.copy()
res1=fun1(arr1)
arr2.sort()
res2=fun2(arr2)
print(arr2,panduan(res1,res2),res1,res2)
def suiji():
arr=[]
for i in range(random.randint(0,15)):
arr.append(random.randint(0,100))
return arr
def panduan(arr1,arr2):
return arr1==arr2
ls=[1,3]
ll=[2]
print(ls.extend(ll))
print(ls)
print(main())
print(fun1([1,3,2]))
4. 寻找两个正序数组的中位数
最新推荐文章于 2025-03-16 17:18:06 发布