Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to design a queue that moves the most recently used element to the end of it in Python
We need to design a queue that moves the most recently used element to the end. The queue is initialized with integers 1 to n, and we implement a function that moves an element from a given position to the end while returning that element's value.
For example, with n = 5 (queue contains [1, 2, 3, 4, 5]) and move operations at positions 5, 2, 3, and 1, the output will be 5, 2, 4, 1 respectively.
Algorithm Steps
To solve this efficiently, we use a square root decomposition approach ?
- Find the correct block index i where the element at position k is located
- Remove the element from its current position in the data structure
- Update all subsequent block indices by decrementing them
- Add the removed element to the end of the queue
- Handle block management (create new blocks or remove empty ones)
- Return the moved element
Implementation
from bisect import bisect_right
from math import sqrt
class TestQueue:
def __init__(self, n):
self.n = n
self.nn = int(sqrt(n)) # Block size
self.data = [] # List of blocks
self.index = [] # Starting indices of each block
# Initialize queue with numbers 1 to n
for i in range(1, n + 1):
block_index = (i - 1) // self.nn
if block_index == len(self.data):
self.data.append([])
self.index.append(i)
self.data[-1].append(i)
def solve(self, k):
# Find which block contains the kth element
i = bisect_right(self.index, k) - 1
# Remove element from its current position
x = self.data[i].pop(k - self.index[i])
# Update indices of subsequent blocks
for ii in range(i + 1, len(self.index)):
self.index[ii] -= 1
# If last block is full, create a new one
if len(self.data[-1]) >= self.nn:
self.data.append([])
self.index.append(self.n)
# Add element to the end
self.data[-1].append(x)
# Remove empty block if necessary
if not self.data[i]:
self.data.pop(i)
self.index.pop(i)
return x
# Example usage
queue = TestQueue(5)
print("Moving element at position 5:", queue.solve(5))
print("Moving element at position 2:", queue.solve(2))
print("Moving element at position 3:", queue.solve(3))
print("Moving element at position 1:", queue.solve(1))
Moving element at position 5: 5 Moving element at position 2: 2 Moving element at position 3: 4 Moving element at position 1: 1
How It Works
The algorithm uses square root decomposition to efficiently handle the move operations ?
- Block Structure: The queue is divided into blocks of size ?n for efficient access
-
Position Tracking: The
indexarray tracks the starting position of each block -
Binary Search:
bisect_right()quickly finds which block contains the target element - Dynamic Management: Blocks are created or removed as needed during operations
Time Complexity
| Operation | Time Complexity | Explanation |
|---|---|---|
| Initialization | O(n) | Create n elements in ?n blocks |
| Move Operation | O(?n) | Find block + update indices |
| Overall | O(m?n) | For m move operations |
Conclusion
This square root decomposition approach efficiently handles the "move to end" queue operations with O(?n) complexity per operation. The algorithm maintains the queue structure while allowing dynamic element repositioning.
