Shuffle String: Index Mapping Pattern
LeetCode Shuffle String (problem 1528) gives you a string s and an integer array indices of the same length. The character at position i in s should move to position indices[i] in the shuffled string. Return the shuffled string.
Given s = "codeleet" and indices = [4, 5, 6, 7, 0, 2, 1, 3], the result is "leetcode". Each character lands at the exact index specified by the corresponding entry in indices.
Why this problem matters
Shuffle String is a clean introduction to the index mapping pattern. You are given a permutation of indices and asked to rearrange data according to that permutation. This exact pattern shows up in problems involving cyclic sort, array rearrangement, and any scenario where a mapping tells you where each element belongs.
The problem is easy, but the underlying idea (building a result by placing elements at their target positions) is a building block you will use in harder problems.
The approach: direct index placement
The idea is simple. Create a result array of the same length as s. Walk through each character in s, and place it directly at the position given by indices[i].
- For each index
i, reads[i]and write it toresult[indices[i]] - After one pass, every character is in its final position
- Join the result array into a string and return it
There is no need to sort, no need to swap in place, and no need for any extra data structures beyond the result array.
def restoreString(s: str, indices: list[int]) -> str:
result = [''] * len(s)
for i, idx in enumerate(indices):
result[idx] = s[i]
return ''.join(result)
That is the entire solution. One pass, one result array, done.
Visual walkthrough: placing characters one by one
Let's trace through s = "codeleet" with indices = [4, 5, 6, 7, 0, 2, 1, 3]. Watch how each character lands in its target position.
Step 1: s[0] = "c" goes to result[4]
Place "c" at index 4. Result so far: [_, _, _, _, "c", _, _, _]
Step 2: s[1] = "o" goes to result[5]
Place "o" at index 5. Result so far: [_, _, _, _, "c", "o", _, _]
Step 3: s[2] = "d" goes to result[6]
Place "d" at index 6. Result so far: [_, _, _, _, "c", "o", "d", _]
Step 4: s[3] = "e" goes to result[7]
Place "e" at index 7. Result so far: [_, _, _, _, "c", "o", "d", "e"]
Step 5: s[4] = "l" goes to result[0]
Place "l" at index 0. Result so far: ["l", _, _, _, "c", "o", "d", "e"]
Step 6: s[5] = "e" goes to result[2]
Place "e" at index 2. Result so far: ["l", _, "e", _, "c", "o", "d", "e"]
Step 7: s[6] = "e" goes to result[1]
Place "e" at index 1. Result so far: ["l", "e", "e", _, "c", "o", "d", "e"]
Step 8: s[7] = "t" goes to result[3]
Place "t" at index 3. Result so far: ["l", "e", "e", "t", "c", "o", "d", "e"]
After all eight placements, the result array contains ["l", "e", "e", "t", "c", "o", "d", "e"], which joins to "leetcode".
Complexity analysis
| Aspect | Value | Why |
|---|---|---|
| Time | O(n) | Single pass through the string |
| Space | O(n) | Result array of length n |
You cannot do better than O(n) time because you must read every character at least once. You also need O(n) space for the result, since strings are immutable in Python (you cannot rearrange characters in place).
The building blocks
This problem uses one core pattern:
Index mapping (permutation placement)
Given an array that tells you where each element should go, build the result by iterating through the source and placing each element at its target index. The key line is:
result[indices[i]] = s[i]
This pattern shows up whenever a problem gives you a permutation or a mapping from current positions to target positions. You will see it in:
- Rotate Array (LeetCode 189) where each element moves to
(i + k) % n - Sort Colors (LeetCode 75) where elements are partitioned into target regions by value
- Move Zeroes (LeetCode 283) where non-zero elements are placed at consecutive target positions
The idea is always the same: read from the source, write to the destination. One pass, linear time.
Edge cases
Single character string. If s has length 1, the result is just s itself. The loop runs once and places the character at indices[0], which must be 0.
Already in order. If indices = [0, 1, 2, ..., n-1], every character stays in place. The algorithm handles this naturally with no special case needed.
Reversed order. If indices = [n-1, n-2, ..., 1, 0], the string is reversed. Again, no special handling required. Each character simply lands at its mirrored position.
The problem guarantees that indices is a valid permutation of [0, 1, ..., n-1]. You do not need to check for duplicates or out-of-bounds values. In an interview, it is still worth mentioning this assumption out loud.
From understanding to recall
You understand how index mapping works now. The solution is short, only three lines of real logic. But understanding it today and producing it from memory next week are two different things.
The trick is repetition. Write the solution from scratch tomorrow. Then again in three days. Then a week later. Each time, you are reinforcing the pattern: create a result array, iterate through the source, place each element at indices[i]. After a few reps, you will not need to think about it. You will just write it.
That is the difference between recognizing a pattern and owning it.
Related posts
- Rotate Array - Another index mapping problem where each element moves to
(i + k) % n. Same idea, different formula. - Sort Colors - Partitioning elements into target regions. The placement logic is more complex, but the core concept of "put each element where it belongs" is the same.
- Move Zeroes - A two-pointer placement problem where non-zero elements are written to consecutive target positions.