4. 寻找两个正序数组的中位数

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]))










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值