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 index array 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.

Updated on: 2026-03-26T14:34:42+05:30

528 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements