The Carousel
An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- easy
- Seniority
- L3
Problem
A status display cycles through a fixed ring of items, and you need to advance its starting point by k slots so the item currently sitting k places along becomes the new front. Return a fresh list holding that left rotation, where k may be zero, larger than the length of lst, or negative (a negative k shifts the ring the other way). An empty lst comes back empty.
Keep moving, same ride.
Example 1
Input:
lst = [1,2,3,4,5], k = 2
Output:
[3,4,5,1,2]
Example 2
Input:
lst = ["a","b","c"], k = 1
Output:
["b","c","a"]
Worked solution and explanation
What this problem really is
Underneath the carousel costume, this is index normalization. The rotation itself is one slice-and-concatenate; the part that actually separates candidates is taming k before you touch the list. A k of 7 on a 3-element list, or a k of -1, both have to land on a clean offset inside [0, n). Get the normalization wrong and you either throw or hand back garbage.
How to get there
Step 1: Bail out on empty input
Guard the empty list first. len([]) is 0, and any modulo against 0 raises ZeroDivisionError, so the empty case has to return before you compute an offset.
Step 2: Normalize the offset
Collapse k into k % len(lst). In Python the result is always in [0, n) even when k is negative, so an oversized or negative k both reduce to the same small left-shift without any special branch.
Step 3: Slice and recombine
Everything from the offset onward comes first, then everything before it. lst[k:] + lst[:k] is the whole rotation in one expression.
The solution
def rotate_left(lst, k):
if not lst:
return []
k = k % len(lst)
return lst[k:] + lst[:k]One modulo absorbs oversized and negative k; one slice does the rest.
- Naive
return lst[k:] + lst[:k]with no modulo. Works for the example inputs, then silently no-ops: oncekreaches or exceedsn,lst[k:]is empty andlst[:k]is the whole list, so it hands back the original order (for k=3 on[1,2,3]you get[1,2,3], not the rotated list). Large negativekfails the same way.- Normalized
k = k % len(lst)first. Everyk, large or negative, maps onto one canonical offset in[0, n), and the same slice expression is now always correct.
Common follow-up questions
- How would you rotate in place with O(1) extra space? (Tests the three-reversal algorithm: reverse the first k, reverse the rest, reverse the whole list.)
- What is the relationship between left and right rotation? (Tests that a left rotation by k equals a right rotation by n - k.)
- What changes if the input is a deque you rotate many times? (Tests collections.deque.rotate(-k) for cheaper repeated rotations.)