You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
4.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

堆 大根堆、小根堆
完全二叉树的概念只有最下面一层,最右边当节点为空
最大线段重合问题
给定很多线段,每个线段都有两个数[start, end],表示线段开始位置和结束位置,左右都是闭区间
规定:
1线段的开始和结束位置一定都是整数值
2线段重合区域的长度必须>=1
返回线段最多重合区域中,包含了几条线段?
1、将所有线段按照start升序排序
2、构造堆保存当前重合所有重合线段的end, heap的size就是当前重合线段的数量
3、遍历所有线段如果出现不重合线段则弹出不重合的线段如果重合则加入end
手动改写堆(非常重要)!
系统提供的堆无法做到的事情:
1已经入堆的元素如果参与排序的指标方法变化系统提供的堆无法做到时间复杂度O(logN)调整都是O(N)的调整!
2系统提供的堆只能弹出堆顶做不到自由删除任何一个堆中的元素或者说无法在时间复杂度O(logN)内完成一定会高于O(logN)
根本原因:无反向索引表
手动改写堆的代码讲解
1建立反向索引表
2建立比较器
3核心在于各种结构相互配合非常容易出错
给定一个整型数组int[] arr和一个布尔类型数组boolean[] op
两个数组一定等长假设长度为Narr[i]表示客户编号op[i]表示客户操作
arr = [ 3 , 3 , 1 , 2, 1, 2, 5…
op = [ T , T, T, T, F, T, F…
依次表示3用户购买了一件商品3用户购买了一件商品1用户购买了一件商品2用户购买了一件商品1用户退货了一件商品2用户购买了一件商品5用户退货了一件商品…
一对arr[i]和op[i]就代表一个事件:
用户号为arr[i]op[i] == T就代表这个用户购买了一件商品
op[i] == F就代表这个用户退货了一件商品
现在你作为电商平台负责人,你想在每一个事件到来的时候,
都给购买次数最多的前K名用户颁奖。
所以每个事件发生后,你都需要一个得奖名单(得奖区)。
得奖系统的规则:
1如果某个用户购买商品数为0但是又发生了退货事件
则认为该事件无效得奖名单和上一个事件发生后一致例子中的5用户
2某用户发生购买商品事件购买商品数+1发生退货事件购买商品数-1
3每次都是最多K个用户得奖K也为传入的参数
如果根据全部规则得奖人数确实不够K个那就以不够的情况输出结果
4得奖系统分为得奖区和候选区任何用户只要购买数>0
一定在这两个区域中的一个
5购买数最大的前K名用户进入得奖区
在最初时如果得奖区没有到达K个用户那么新来的用户直接进入得奖区
6如果购买数不足以进入得奖区的用户进入候选区
7如果候选区购买数最多的用户已经足以进入得奖区
该用户就会替换得奖区中购买数最少的用户(大于才能替换),
如果得奖区中购买数最少的用户有多个,就替换最早进入得奖区的用户
如果候选区中购买数最多的用户有多个,机会会给最早进入候选区的用户
8候选区和得奖区是两套时间
因用户只会在其中一个区域,所以只会有一个区域的时间,另一个没有
从得奖区出来进入候选区的用户,得奖区时间删除,
进入候选区的时间就是当前事件的时间可以理解为arr[i]和op[i]中的i
从候选区出来进入得奖区的用户,候选区时间删除,
进入得奖区的时间就是当前事件的时间可以理解为arr[i]和op[i]中的i
9如果某用户购买数==0不管在哪个区域都离开区域时间删除
离开是指彻底离开,哪个区域也不会找到该用户
如果下次该用户又发生购买行为,产生>0的购买数
会再次根据之前规则回到某个区域中,进入区域的时间重记
请遍历arr数组和op数组遍历每一步输出一个得奖名单
public List<List<Integer>> topK (int[] arr, boolean[] op, int k)