Welcome to Subscribe On Youtube
1756. Design Most Recently Used Queue
Description
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 theMRUQueue
withn
elements:[1,2,3,...,n]
.int fetch(int k)
moves thekth
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 tofetch
.
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
-
class BinaryIndexedTree { private int n; private int[] c; public BinaryIndexedTree(int n) { this.n = n; this.c = new int[n + 1]; } public void update(int x, int v) { while (x <= n) { c[x] += v; x += x & -x; } } public int query(int x) { int s = 0; while (x > 0) { s += c[x]; x -= x & -x; } return s; } } class MRUQueue { private int n; private int[] q; private BinaryIndexedTree tree; public MRUQueue(int n) { this.n = n; q = new int[n + 2010]; for (int i = 1; i <= n; ++i) { q[i] = i; } tree = new BinaryIndexedTree(n + 2010); } public int fetch(int k) { int l = 1, r = n; while (l < r) { int mid = (l + r) >> 1; if (mid - tree.query(mid) >= k) { r = mid; } else { l = mid + 1; } } int x = q[l]; q[++n] = x; tree.update(l, 1); return x; } } /** * Your MRUQueue object will be instantiated and called as such: * MRUQueue obj = new MRUQueue(n); * int param_1 = obj.fetch(k); */
-
class BinaryIndexedTree { public: BinaryIndexedTree(int _n) : n(_n) , c(_n + 1) {} void update(int x, int delta) { while (x <= n) { c[x] += delta; x += x & -x; } } int query(int x) { int s = 0; while (x) { s += c[x]; x -= x & -x; } return s; } private: int n; vector<int> c; }; class MRUQueue { public: MRUQueue(int n) { q.resize(n + 1); iota(q.begin() + 1, q.end(), 1); tree = new BinaryIndexedTree(n + 2010); } int fetch(int k) { int l = 1, r = q.size(); while (l < r) { int mid = (l + r) >> 1; if (mid - tree->query(mid) >= k) { r = mid; } else { l = mid + 1; } } int x = q[l]; q.push_back(x); tree->update(l, 1); return x; } 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); */
-
class MRUQueue: def __init__(self, n: int): self.q = list(range(1, n + 1)) def fetch(self, k: int) -> int: ans = self.q[k - 1] self.q[k - 1 : k] = [] self.q.append(ans) return ans # Your MRUQueue object will be instantiated and called as such: # obj = MRUQueue(n) # param_1 = obj.fetch(k)
-
type BinaryIndexedTree struct { n int c []int } func newBinaryIndexedTree(n int) *BinaryIndexedTree { c := make([]int, n+1) return &BinaryIndexedTree{n, c} } func (this *BinaryIndexedTree) update(x, delta int) { for x <= this.n { this.c[x] += delta x += x & -x } } func (this *BinaryIndexedTree) query(x int) int { s := 0 for x > 0 { s += this.c[x] x -= x & -x } return s } type MRUQueue struct { q []int tree *BinaryIndexedTree } func Constructor(n int) MRUQueue { q := make([]int, n+1) for i := 1; i <= n; i++ { q[i] = i } return MRUQueue{q, newBinaryIndexedTree(n + 2010)} } func (this *MRUQueue) Fetch(k int) int { l, r := 1, len(this.q) for l < r { mid := (l + r) >> 1 if mid-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) return x } /** * Your MRUQueue object will be instantiated and called as such: * obj := Constructor(n); * param_1 := obj.Fetch(k); */
-
class BinaryIndexedTree { private n: number; private c: number[]; constructor(n: number) { this.n = n; this.c = new Array(n + 1).fill(0); } public update(x: number, v: number): void { while (x <= this.n) { this.c[x] += v; x += x & -x; } } public query(x: number): number { let s = 0; while (x > 0) { s += this.c[x]; x -= x & -x; } return s; } } class MRUQueue { private q: number[]; private tree: BinaryIndexedTree; constructor(n: number) { this.q = new Array(n + 1); for (let i = 1; i <= n; ++i) { this.q[i] = i; } this.tree = new BinaryIndexedTree(n + 2010); } fetch(k: number): number { let l = 1; let r = this.q.length; while (l < r) { const mid = (l + r) >> 1; if (mid - this.tree.query(mid) >= k) { r = mid; } else { l = mid + 1; } } const x = this.q[l]; this.q.push(x); this.tree.update(l, 1); return x; } } /** * Your MRUQueue object will be instantiated and called as such: * var obj = new MRUQueue(n) * var param_1 = obj.fetch(k) */