Design a queue-like data structure that moves the most recently used element to the end of the queue.
Implement the MRUQueue class:
MRUQueue(int n) constructs the MRUQueue with n elements: [1,2,3,...,n].
int fetch(int k) moves the kth element (1-indexed) to the end of the queue and returns it.
Example 1:
Input:
["MRUQueue", "fetch", "fetch", "fetch", "fetch"]
[[8], [3], [5], [2], [8]]
Output:
[null, 3, 6, 2, 2]
Explanation:
MRUQueue mRUQueue = new MRUQueue(8); // Initializes the queue to [1,2,3,4,5,6,7,8].
mRUQueue.fetch(3); // Moves the 3rd element (3) to the end of the queue to become [1,2,4,5,6,7,8,3] and returns it.
mRUQueue.fetch(5); // Moves the 5th element (6) to the end of the queue to become [1,2,4,5,7,8,3,6] and returns it.
mRUQueue.fetch(2); // Moves the 2nd element (2) to the end of the queue to become [1,4,5,7,8,3,6,2] and returns it.
mRUQueue.fetch(8); // The 8th element (2) is already at the end of the queue so just return it.
Constraints:
1 <= n <= 2000
1 <= k <= n
At most 2000 calls will be made to fetch.
Follow up: Finding an O(n) algorithm per fetch is a bit easy. Can you find an algorithm with a better complexity for each fetch call?
Solutions
Solution 1
1 2 3 4 5 6 7 8 91011121314
classMRUQueue:def__init__(self,n:int):self.q=list(range(1,n+1))deffetch(self,k:int)->int:ans=self.q[k-1]self.q[k-1:k]=[]self.q.append(ans)returnans# Your MRUQueue object will be instantiated and called as such:# obj = MRUQueue(n)# param_1 = obj.fetch(k)
classBinaryIndexedTree{privateintn;privateint[]c;publicBinaryIndexedTree(intn){this.n=n;this.c=newint[n+1];}publicvoidupdate(intx,intv){while(x<=n){c[x]+=v;x+=x&-x;}}publicintquery(intx){ints=0;while(x>0){s+=c[x];x-=x&-x;}returns;}}classMRUQueue{privateintn;privateint[]q;privateBinaryIndexedTreetree;publicMRUQueue(intn){this.n=n;q=newint[n+2010];for(inti=1;i<=n;++i){q[i]=i;}tree=newBinaryIndexedTree(n+2010);}publicintfetch(intk){intl=1,r=n;while(l<r){intmid=(l+r)>>1;if(mid-tree.query(mid)>=k){r=mid;}else{l=mid+1;}}intx=q[l];q[++n]=x;tree.update(l,1);returnx;}}/** * Your MRUQueue object will be instantiated and called as such: * MRUQueue obj = new MRUQueue(n); * int param_1 = obj.fetch(k); */
classBinaryIndexedTree{public:BinaryIndexedTree(int_n):n(_n),c(_n+1){}voidupdate(intx,intdelta){while(x<=n){c[x]+=delta;x+=x&-x;}}intquery(intx){ints=0;while(x){s+=c[x];x-=x&-x;}returns;}private:intn;vector<int>c;};classMRUQueue{public:MRUQueue(intn){q.resize(n+1);iota(q.begin()+1,q.end(),1);tree=newBinaryIndexedTree(n+2010);}intfetch(intk){intl=1,r=q.size();while(l<r){intmid=(l+r)>>1;if(mid-tree->query(mid)>=k){r=mid;}else{l=mid+1;}}intx=q[l];q.push_back(x);tree->update(l,1);returnx;}private:vector<int>q;BinaryIndexedTree*tree;};/** * Your MRUQueue object will be instantiated and called as such: * MRUQueue* obj = new MRUQueue(n); * int param_1 = obj->fetch(k); */
typeBinaryIndexedTreestruct{nintc[]int}funcnewBinaryIndexedTree(nint)*BinaryIndexedTree{c:=make([]int,n+1)return&BinaryIndexedTree{n,c}}func(this*BinaryIndexedTree)update(x,deltaint){forx<=this.n{this.c[x]+=deltax+=x&-x}}func(this*BinaryIndexedTree)query(xint)int{s:=0forx>0{s+=this.c[x]x-=x&-x}returns}typeMRUQueuestruct{q[]inttree*BinaryIndexedTree}funcConstructor(nint)MRUQueue{q:=make([]int,n+1)fori:=1;i<=n;i++{q[i]=i}returnMRUQueue{q,newBinaryIndexedTree(n+2010)}}func(this*MRUQueue)Fetch(kint)int{l,r:=1,len(this.q)forl<r{mid:=(l+r)>>1ifmid-this.tree.query(mid)>=k{r=mid}else{l=mid+1}}x:=this.q[l]this.q=append(this.q,x)this.tree.update(l,1)returnx}/** * Your MRUQueue object will be instantiated and called as such: * obj := Constructor(n); * param_1 := obj.Fetch(k); */
classBinaryIndexedTree{privaten:number;privatec:number[];constructor(n:number){this.n=n;this.c=newArray(n+1).fill(0);}publicupdate(x:number,v:number):void{while(x<=this.n){this.c[x]+=v;x+=x&-x;}}publicquery(x:number):number{lets=0;while(x>0){s+=this.c[x];x-=x&-x;}returns;}}classMRUQueue{privateq:number[];privatetree:BinaryIndexedTree;constructor(n:number){this.q=newArray(n+1);for(leti=1;i<=n;++i){this.q[i]=i;}this.tree=newBinaryIndexedTree(n+2010);}fetch(k:number):number{letl=1;letr=this.q.length;while(l<r){constmid=(l+r)>>1;if(mid-this.tree.query(mid)>=k){r=mid;}else{l=mid+1;}}constx=this.q[l];this.q.push(x);this.tree.update(l,1);returnx;}}/** * Your MRUQueue object will be instantiated and called as such: * var obj = new MRUQueue(n) * var param_1 = obj.fetch(k) */
classBinaryIndexedTree:def__init__(self,n:int):self.n=nself.c=[0]*(n+1)defupdate(self,x:int,v:int):whilex<=self.n:self.c[x]+=vx+=x&-xdefquery(self,x:int)->int:s=0whilex:s+=self.c[x]x-=x&-xreturnsclassMRUQueue:def__init__(self,n:int):self.q=list(range(n+1))self.tree=BinaryIndexedTree(n+2010)deffetch(self,k:int)->int:l,r=1,len(self.q)whilel<r:mid=(l+r)>>1ifmid-self.tree.query(mid)>=k:r=midelse:l=mid+1x=self.q[l]self.q.append(x)self.tree.update(l,1)returnx# Your MRUQueue object will be instantiated and called as such:# obj = MRUQueue(n)# param_1 = obj.fetch(k)