算法系列06——加强堆(手动改写堆)

  • 建立反向索引表
  • 建立比较器
  • 核心在于各种结构相互配合
  • 最大线段重合问题
    • 题目详细
      • 每一个线段的开始和结束位置都是整数
      • 重合区域长度大于等于1才叫重合
      • 返回一个重合区域,使区域上的重合线段数量最多是多少
    • 第一种暴力
      • 先找最小的开始位置和最大的结束位置
      • 考察这个区域上的每一个点5,因为一个重合区域必然包含一个点5
      • 算出每一个点5的位置被多少的线段覆盖,取最大值
      • 复杂度是(max - min) * N,受制于max-min
    • 好办法
      • 根据开始位置从小到大将所有线段排序
      • 准备一个小根堆
      • 从排好序的数组种依此取出线段
        • 看这个线段的开始,小根堆种弹出比这个开始小于等于的数
        • 看这个线段的结束,小根堆中压入这个结束
        • 记录当前堆中留下的数的个数
          • 含义是以当前线段的开始为左边界,越过这里的有几条线段
      • 记录下的留下的数的个数中最大的那个就是答案
    • 关于理解
      • 每一个重合部分的左边界,都是某个线段的左边界

面试中的数据量限制

  • 一般c++给1-2s
  • java给2-4s
  • 指的是代码条数在108-109,一般控制指令条数在108

加强堆

  • 对于一个堆来说,如果改变堆中某一个位置的值,这个堆就变成了无效堆
  • 如果这个值比原来大,应该要heapify,如果比原来小,应该要heapinsert
  • 但是系统实现的堆不支持这种操作
  • 系统不能高效的完成这样的操作,是因为系统建立的堆没有反向索引表
    • 数组本身代表一张索引表,从下标索引到存储的元素
    • 但是不能从元素映射回下标位置,只能遍历找到修改了值的那个元素
  • 自己加反向索引表就能做到logN的代价
  • c++委员会会提供带反向索引的堆,但偏实用的包中不会提供
  • 反向索引表的写法,在堆中增加一个hashmap,indexMap
  • arryList的get和set是O(1)复杂度
  • 目前的模板是非基础类型,有基础类型需求就要包一层,这是hashmap的设计原因
  • 将反向索引表的修改直接封装到交换操作里,保证反向索引表与动态数组同步
  • 弹出的时候要反向索引表删除这个弹出的值,压入的时候反向索引表也要增加这个值
  • 修改了某一个值就是顺序进行heapInsert,heapify,因为值要么变大要么变小,实际上只会执行二者之一,logn就能完成修改某一个值,非常高效
  • 还可以实现高效的删除某一个值,系统只能删除堆顶
    • 首先找到这个要删除的值在哪里
    • 然后用堆最后一个元素与这个值进行交换,删掉最后一个,替换后的位置上顺序进行heapInsert,heapify
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值