栈是先进后出的,队列 是先进先出的
如何用栈结构实现队列结构
解析:用两个栈,一个push栈,一个pop栈,当pop栈没有数后,将push栈所有的数倒到pop栈中
如何用队列结构实现栈结构
解析:用两个队列,A和B,假如,从A进数,当需要弹出时,将A队列中的除了最后一个数,全部
推到B队列中,再弹出A队列的数,以此类推
最大线段重合问题
定义:给定很多线段,每个线段都有两个数[start, end],
表示线段开始位置和结束位置,左右都是闭区间
规定:
1)线段的开始和结束位置一定都是整数值
2)线段重合区域的长度必须>=1
返回线段最多重合区域中,包含了几条线段
解析:1.将所有的线段都进行以左节点从小到大排序
2.创建一个小根堆,将每个线段的左节点跟小根堆里的值进行比较,将小于等于左节点的值弹出,并将此线段的右节点放入堆中,小根堆有多少值就是以此左节点为起始的线段重合的次数
3.取出最大值
与堆有关的题目
题目:已知一个几乎有序的数组。几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离一定不超过k,并且k相对于数组长度来说是比较小的。请选择一个合适的排序策略,对这个数组进行排序。
解析:排好序后0位置的数只会出现在0-k之间
所以创建一个k+1的小根堆,每次弹出一个数,并insert一个数
手动改写堆
系统提供的堆无法做到的事情:
1)已经入堆的元素,如果参与排序的指标方法变化,
系统提供的堆无法做到时间复杂度O(logN)调整!都是O(N)的调整!
2)系统提供的堆只能弹出堆顶,做不到自由删除任何一个堆中的元素,
或者说,无法在时间复杂度O(logN)内完成!一定会高于O(logN)
根本原因:无反向索引表
解析:1.一个索引,对象的list
2.一个对象,索引的list\
手动改写堆题目练习
得奖系统的规则:
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> topK (int[] arr, boolean[] op, int k)
解析:
1.创建两个加强堆,一个加强大根堆作为等待区,一个加强小根堆,作为得奖区,写好各自的比较器,
每次事件结束后,看等待区的最大值是否能把小根堆里的最小值干掉