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 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
9
10
11
12
13
14
| 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)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| 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);
*/
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| 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)
*/
|
Solution 2#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| class BinaryIndexedTree:
def __init__(self, n: int):
self.n = n
self.c = [0] * (n + 1)
def update(self, x: int, v: int):
while x <= self.n:
self.c[x] += v
x += x & -x
def query(self, x: int) -> int:
s = 0
while x:
s += self.c[x]
x -= x & -x
return s
class MRUQueue:
def __init__(self, n: int):
self.q = list(range(n + 1))
self.tree = BinaryIndexedTree(n + 2010)
def fetch(self, k: int) -> int:
l, r = 1, len(self.q)
while l < r:
mid = (l + r) >> 1
if mid - self.tree.query(mid) >= k:
r = mid
else:
l = mid + 1
x = self.q[l]
self.q.append(x)
self.tree.update(l, 1)
return x
# Your MRUQueue object will be instantiated and called as such:
# obj = MRUQueue(n)
# param_1 = obj.fetch(k)
|