Design Most Recently Used Queue
MediumUpdated: Aug 2, 2025
Practice on:
Problem
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 theMRUQueuewithnelements:[1,2,3,...,n].int fetch(int k)moves thekthelement (1-indexed) to the end of the queue and returns it.
Examples
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 <= 20001 <= k <= n- At most
2000calls 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?
Solution
Method 1 – List with Direct Access (O(n) per fetch)
Intuition
We can use a simple list/array to represent the queue. For each fetch, we remove the k-th element and append it to the end. This is straightforward and works well for small n (as in constraints).
Approach
- Store the queue as a list of integers from 1 to n.
- For
fetch(k), remove the (k-1)-th element and append it to the end, then return it. - This is O(n) per fetch, which is acceptable for n ≤ 2000.
Code
C++
class MRUQueue {
vector<int> q;
public:
MRUQueue(int n) {
for (int i = 1; i <= n; ++i) q.push_back(i);
}
int fetch(int k) {
int ans = q[k-1];
q.erase(q.begin() + k-1);
q.push_back(ans);
return ans;
}
};
Go
type MRUQueue struct {
q []int
}
func Constructor(n int) MRUQueue {
q := make([]int, n)
for i := 0; i < n; i++ {
q[i] = i + 1
}
return MRUQueue{q}
}
func (m *MRUQueue) Fetch(k int) int {
ans := m.q[k-1]
m.q = append(m.q[:k-1], m.q[k:]...)
m.q = append(m.q, ans)
return ans
}
Java
public class MRUQueue {
private List<Integer> q;
public MRUQueue(int n) {
q = new ArrayList<>();
for (int i = 1; i <= n; ++i) q.add(i);
}
public int fetch(int k) {
int ans = q.get(k-1);
q.remove(k-1);
q.add(ans);
return ans;
}
}
Kotlin
class MRUQueue(n: Int) {
private val q = MutableList(n) { it + 1 }
fun fetch(k: Int): Int {
val ans = q[k-1]
q.removeAt(k-1)
q.add(ans)
return ans
}
}
Python
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.pop(k-1)
self.q.append(ans)
return ans
Rust
struct MRUQueue {
q: Vec<i32>,
}
impl MRUQueue {
fn new(n: i32) -> Self {
Self { q: (1..=n).collect() }
}
fn fetch(&mut self, k: i32) -> i32 {
let idx = (k-1) as usize;
let ans = self.q[idx];
self.q.remove(idx);
self.q.push(ans);
ans
}
}
TypeScript
class MRUQueue {
private q: number[];
constructor(n: number) {
this.q = Array.from({length: n}, (_, i) => i + 1);
}
fetch(k: number): number {
const ans = this.q[k-1];
this.q.splice(k-1, 1);
this.q.push(ans);
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n)per fetch, since removing from the middle of a list is O(n). - 🧺 Space complexity:
O(n), for storing the queue.