An array can be rotated to the right in Python using several methods, ranging from the concise and expressive slicing technique to more performant in-place algorithms.
A rotation of k steps means the last k elements move to the front of the array, and the rest of the elements shift to the right.
Method 1: Using slicing (easiest way)
This is the most common and Pythonic way to rotate a list. It is highly readable and best for most everyday tasks.
How it works:
- Use the modulus operator (
%) to handle cases where k is larger than the array's length (n), as rotating n times brings the array back to its original state. - Create a new list by concatenating two slices: the last
kelements (nums[-k:]) and the firstn-kelements (nums[:-k]).
Code:
def rotate_right_slicing(nums: list, k: int) -> list:
"""
Rotates a list to the right by k positions using slicing.
Args:
nums: The list to rotate.
k: The number of positions to rotate.
Returns:
The new, rotated list.
"""
if not nums:
return nums
n = len(nums)
k = k % n # Handle cases where k > n
return nums[-k:] + nums[:-k]
# Example usage:
my_list = [1, 2, 3, 4, 5, 6, 7]
k = 3
rotated_list = rotate_right_slicing(my_list, k)
print(f"Original list: {my_list}")
print(f"Rotated list: {rotated_list}")
# Output:
# Original list: [1, 2, 3, 4, 5, 6, 7]
# Rotated list: [5, 6, 7, 1, 2, 3, 4]
Use code with caution.
Complexity analysis:
-
**Time complexity:**O(n)cap O open paren n close paren
𝑂(𝑛)
, where nn
𝑛
is the number of elements in the list. This is because slicing and concatenating lists in Python both create new lists and take time proportional to their size.
-
**Space complexity:**O(n)cap O open paren n close paren
𝑂(𝑛)
, as a new list is created to store the result.
Method 2: Using collections.deque (most efficient for multiple rotations)
The deque (double-ended queue) data structure, from Python's collections module, is optimized for appends and pops from both ends. It has a built-in rotate() method that is very efficient for this task.
How it works:
- Convert the list to a
dequeobject. - Use the
rotate()method with a positive integerkto rotate the elements to the right. - Convert the
dequeback into a list if needed.
Code:
from collections import deque
def rotate_right_deque(nums: list, k: int):
"""
Rotates a list to the right by k positions using deque.
This modifies the list in place if a reference is kept.
Args:
nums: The list to rotate.
k: The number of positions to rotate.
"""
if not nums:
return
n = len(nums)
d = deque(nums)
d.rotate(k)
nums[:] = list(d) # Modify original list in-place
# Example usage:
my_list = [1, 2, 3, 4, 5, 6, 7]
k = 3
rotate_right_deque(my_list, k)
print(f"Rotated list (deque method): {my_list}")
# Output:
# Rotated list (deque method): [5, 6, 7, 1, 2, 3, 4]
Use code with caution.
Complexity analysis:
-
**Time complexity:**O(n)cap O open paren n close paren
𝑂(𝑛)
to convert the list to a deque and back, but the rotation itself is highly optimized. It's often faster for large arrays and frequent rotations.
-
**Space complexity:**O(n)cap O open paren n close paren
𝑂(𝑛)
, as it requires temporary space for the
dequeobject.
Method 3: Using the reversal algorithm (in-place)
For interviews or scenarios where memory usage is critical, an in-place algorithm that modifies the array directly without using extra space is a good solution. The reversal algorithm achieves this by performing three reversals.
How it works:
- Reverse the entire array. This brings the elements that should be at the end to the front, but in the wrong order.
- Reverse the first
kelements. This corrects the order of the lastkelements. - Reverse the remaining
n-kelements. This corrects the order of the firstn-kelements.
Code:
def reverse(nums: list, start: int, end: int):
"""Helper function to reverse a portion of a list."""
while start < end:
nums[start], nums[end] = nums[end], nums[start]
start += 1
end -= 1
def rotate_right_reversal(nums: list, k: int):
"""
Rotates a list to the right by k positions in-place using the reversal method.
Args:
nums: The list to rotate.
k: The number of positions to rotate.
"""
if not nums:
return
n = len(nums)
k %= n
# Reverse the entire list
reverse(nums, 0, n - 1)
# Reverse the first k elements
reverse(nums, 0, k - 1)
# Reverse the remaining n-k elements
reverse(nums, k, n - 1)
# Example usage:
my_list = [1, 2, 3, 4, 5, 6, 7]
k = 3
rotate_right_reversal(my_list, k)
print(f"Rotated list (reversal method): {my_list}")
# Output:
# Rotated list (reversal method): [5, 6, 7, 1, 2, 3, 4]
Use code with caution.
Complexity analysis:
-
**Time complexity:**O(n)cap O open paren n close paren
𝑂(𝑛)
, as each element is reversed a constant number of times (at most three).
-
**Space complexity:**O(1)cap O open paren 1 close paren
𝑂(1)
, because the rotation is performed in-place without allocating a new list.
Method 4: Repeatedly popping and inserting
This is a straightforward, though inefficient, brute-force approach. It simulates the rotation one step at a time.
How it works:
- Loop
ktimes. - In each loop, use
pop()to remove the last element. - Use
insert()to add that element to the front of the list.
Code:
def rotate_right_brute_force(nums: list, k: int):
"""
Rotates a list to the right by k positions using repeated pop and insert.
Args:
nums: The list to rotate.
k: The number of positions to rotate.
"""
if not nums:
return
n = len(nums)
k %= n
for _ in range(k):
last_element = nums.pop()
nums.insert(0, last_element)
# Example usage:
my_list = [1, 2, 3, 4, 5, 6, 7]
k = 3
rotate_right_brute_force(my_list, k)
print(f"Rotated list (brute force): {my_list}")
# Output:
# Rotated list (brute force): [5, 6, 7, 1, 2, 3, 4]
Use code with caution.
Complexity analysis:
-
**Time complexity:**O(n*k)cap O open paren n * k close paren
𝑂(𝑛*𝑘)
. The
pop(0)andinsert(0, ...)operations on a standard Python list are O(n)cap O open paren n close paren𝑂(𝑛)
because all other elements must be shifted. Performing this
ktimes results in a high time complexity. This method is not recommended for large lists or large values ofk. -
**Space complexity:**O(1)cap O open paren 1 close paren
𝑂(1)
, as the operation is performed in-place.
Choosing the right method
| Method | Best for | Pros | Cons |
|---|---|---|---|
| Slicing | Quick, readable, and general use | Simple, expressive, "Pythonic" | Uses extra memory proportional to the list size |
collections.deque |
Multiple or large rotations, efficiency | Extremely fast for deque operations | Requires importing deque, uses extra memory for the deque object |
| Reversal Algorithm | In-place rotation, memory constraints, interviews | O(1)cap O open paren 1 close paren 𝑂(1) space complexity | Less intuitive than slicing, but highly efficient |
| Brute Force | Educational purposes, very small lists | Simple to understand | Very slow, poor performance for larger inputs |