1528. Shuffle String
Problem Description
You are given a string s
and an integer array indices
where both have the same length. Your task is to rearrange the characters of the string based on the positions specified in the indices
array.
The shuffling works as follows: the character currently at position i
in the original string s
should be moved to position indices[i]
in the final shuffled string.
For example, if s = "abc"
and indices = [2, 0, 1]
:
- The character at position 0 ('a') moves to position
indices[0] = 2
- The character at position 1 ('b') moves to position
indices[1] = 0
- The character at position 2 ('c') moves to position
indices[2] = 1
- The resulting shuffled string would be "bca"
The solution creates an array ans
of the same length as the input string. It then iterates through each character in the original string along with its index i
. For each character c
at position i
, it places that character at position indices[i]
in the answer array. Finally, it joins all characters in the answer array to form the shuffled string.
The time complexity is O(n)
where n
is the length of the string, as we iterate through the string once. The space complexity is also O(n)
for storing the result array.
Intuition
The key insight is to understand what the indices
array is telling us. Each value indices[i]
represents the destination position for the character at position i
in the original string.
Instead of trying to track where each character comes from, we can directly place each character where it needs to go. Think of it like having a set of letters and an instruction manual that tells you exactly where to place each letter.
When we see that indices[i] = j
, this means "take the character at position i
and put it at position j
in the result". This is a direct mapping relationship.
The natural approach is to:
- Create an empty result array of the same size as our string
- Go through each character in the original string one by one
- For each character at position
i
, look up where it should go (indices[i]
) - Place that character directly at its destination position
This works because the indices
array guarantees that each position from 0
to n-1
appears exactly once (it's a permutation), ensuring every position in our result will be filled with exactly one character.
The beauty of this solution is its simplicity - we don't need to reverse any mappings or perform complex swaps. We simply read the instructions and place each character exactly where it belongs in a single pass through the string.
Solution Approach
The implementation follows a straightforward direct placement strategy:
-
Initialize Result Array: Create an array
ans
of the same length as the input strings
. Initially, we can fill it with any placeholder values (here using0
), as all positions will be overwritten.ans = [0] * len(s)
-
Iterate and Place Characters: Use
enumerate()
to iterate through the strings
, which gives us both the indexi
and the characterc
at that position.for i, c in enumerate(s):
-
Direct Placement: For each character
c
at positioni
, place it directly at its destination positionindices[i]
in the result array.ans[indices[i]] = c
This is the core operation - we're using
indices[i]
as the index to determine where characterc
should go in the final arrangement. -
Convert to String: After all characters have been placed in their correct positions, join the array elements to form the final string.
return ''.join(ans)
Example Walkthrough:
If s = "codeleet"
and indices = [4,5,6,7,0,2,1,3]
:
- Character 'c' at position 0 goes to position 4:
ans[4] = 'c'
- Character 'o' at position 1 goes to position 5:
ans[5] = 'o'
- Character 'd' at position 2 goes to position 6:
ans[6] = 'd'
- And so on...
After processing all characters, ans = ['l','e','e','t','c','o','d','e']
, which joins to form "leetcode"
.
The algorithm uses an array as the primary data structure for efficient O(1) access when placing characters at specific positions. The pattern here is index mapping - using one array's values as indices for another array.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example with s = "cab"
and indices = [2, 0, 1]
.
Step 1: Initialize Result Array
- Create an array
ans
with length 3 (same as string length) ans = [_, _, _]
(placeholders shown as underscores)
Step 2: Process Each Character
Iteration 1 (i=0):
- Current character:
c
at position 0 - Destination:
indices[0] = 2
- Place 'c' at position 2:
ans[2] = 'c'
- Result:
ans = [_, _, 'c']
Iteration 2 (i=1):
- Current character:
a
at position 1 - Destination:
indices[1] = 0
- Place 'a' at position 0:
ans[0] = 'a'
- Result:
ans = ['a', _, 'c']
Iteration 3 (i=2):
- Current character:
b
at position 2 - Destination:
indices[2] = 1
- Place 'b' at position 1:
ans[1] = 'b'
- Result:
ans = ['a', 'b', 'c']
Step 3: Convert to String
- Join the array:
''.join(['a', 'b', 'c'])
- Final result:
"abc"
The key insight: each indices[i]
value tells us exactly where the character at position i
should go in the final string. We simply follow these instructions directly, placing each character at its designated spot.
Solution Implementation
1class Solution:
2 def restoreString(self, s: str, indices: List[int]) -> str:
3 """
4 Restores a shuffled string to its original order based on given indices.
5
6 Args:
7 s: The shuffled string to be restored
8 indices: List where indices[i] indicates the position where s[i] should be placed
9
10 Returns:
11 The restored string with characters in their correct positions
12 """
13 # Initialize a result list with the same length as the input string
14 result = [''] * len(s)
15
16 # Iterate through each character and its index in the original string
17 for current_index, character in enumerate(s):
18 # Place the character at its target position specified by indices array
19 target_position = indices[current_index]
20 result[target_position] = character
21
22 # Join all characters in the result list to form the final string
23 return ''.join(result)
24
1class Solution {
2 /**
3 * Restores a shuffled string to its original order based on given indices.
4 * Each character at position i in the input string should be placed at position indices[i] in the result.
5 *
6 * @param s The shuffled input string
7 * @param indices Array where indices[i] indicates the target position for character s[i]
8 * @return The restored string with characters rearranged according to indices
9 */
10 public String restoreString(String s, int[] indices) {
11 // Get the length of the input string
12 int length = s.length();
13
14 // Create a character array to build the result string
15 char[] resultArray = new char[length];
16
17 // Iterate through each character in the input string
18 for (int i = 0; i < length; i++) {
19 // Place the character at position i into its target position
20 // indices[i] tells us where character s.charAt(i) should go
21 resultArray[indices[i]] = s.charAt(i);
22 }
23
24 // Convert the character array to a String and return
25 return String.valueOf(resultArray);
26 }
27}
28
1class Solution {
2public:
3 string restoreString(string s, vector<int>& indices) {
4 // Get the length of the input string
5 int n = s.size();
6
7 // Initialize result string with n characters (using space character as placeholder)
8 string result(n, ' ');
9
10 // Iterate through each character in the original string
11 for (int i = 0; i < n; ++i) {
12 // Place character s[i] at its target position indices[i]
13 // indices[i] tells us where character s[i] should go in the result
14 result[indices[i]] = s[i];
15 }
16
17 // Return the restored string
18 return result;
19 }
20};
21
1/**
2 * Restores a shuffled string to its original order based on given indices
3 * @param s - The shuffled string to restore
4 * @param indices - Array where indices[i] indicates the position where s[i] should be placed
5 * @returns The restored string with characters in their correct positions
6 */
7function restoreString(s: string, indices: number[]): string {
8 // Initialize an array to hold characters in their restored positions
9 const restoredArray: string[] = [];
10
11 // Iterate through each character in the input string
12 for (let i = 0; i < s.length; i++) {
13 // Place the character at position i into its target position specified by indices[i]
14 restoredArray[indices[i]] = s[i];
15 }
16
17 // Join the array elements to form the final restored string
18 return restoredArray.join('');
19}
20
Time and Space Complexity
Time Complexity: O(n)
where n
is the length of the string s
.
- The code iterates through the string once using
enumerate(s)
, which takesO(n)
time - Each iteration performs a constant time operation of assigning a character to a specific index in the
ans
array - The
''.join(ans)
operation at the end also takesO(n)
time to concatenate all characters - Total:
O(n) + O(n) = O(n)
Space Complexity: O(n)
where n
is the length of the string s
.
- The
ans
list is created with sizen
to store the rearranged characters, requiringO(n)
space - The output string created by
''.join(ans)
also requiresO(n)
space, but this is typically considered part of the output and not counted as auxiliary space - No other significant auxiliary space is used
- Total auxiliary space:
O(n)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Confusing the Direction of Index Mapping
The most common mistake is misunderstanding which way the index mapping works. Many people initially think that indices[i]
tells us where to get the character FROM, rather than where to PUT the character TO.
Incorrect Understanding:
# WRONG: This treats indices[i] as the source position result[i] = s[indices[i]] # This would be incorrect!
Correct Understanding:
# RIGHT: indices[i] tells us the destination for s[i] result[indices[i]] = s[i]
Example to Illustrate the Difference:
- Given
s = "abc"
andindices = [2, 0, 1]
- Wrong approach would produce:
result[0] = s[2] = 'c'
,result[1] = s[0] = 'a'
,result[2] = s[1] = 'b'
→ "cab" - Correct approach produces:
result[2] = s[0] = 'a'
,result[0] = s[1] = 'b'
,result[1] = s[2] = 'c'
→ "bca"
2. Using String Concatenation Instead of List
Building the result using string concatenation is inefficient and can lead to errors when trying to assign to specific indices:
Inefficient/Error-prone:
result = ""
for i, c in enumerate(s):
result[indices[i]] = c # ERROR: strings are immutable!
Better Approach:
result = [''] * len(s) # Use a list for O(1) index assignment
for i, c in enumerate(s):
result[indices[i]] = c
return ''.join(result)
3. Not Handling Edge Cases
While the problem typically guarantees valid input, in real scenarios you might want to validate:
- Empty string or empty indices array
- Mismatched lengths between
s
andindices
- Invalid indices (duplicates or out of range)
Robust Solution with Validation:
def restoreString(self, s: str, indices: List[int]) -> str:
# Validate input
if not s or not indices:
return s
if len(s) != len(indices):
raise ValueError("String and indices must have the same length")
# Check for valid indices (optional validation)
if len(set(indices)) != len(indices) or min(indices) < 0 or max(indices) >= len(s):
raise ValueError("Invalid indices array")
result = [''] * len(s)
for i, c in enumerate(s):
result[indices[i]] = c
return ''.join(result)
What's the output of running the following function using input 56
?
1KEYBOARD = {
2 '2': 'abc',
3 '3': 'def',
4 '4': 'ghi',
5 '5': 'jkl',
6 '6': 'mno',
7 '7': 'pqrs',
8 '8': 'tuv',
9 '9': 'wxyz',
10}
11
12def letter_combinations_of_phone_number(digits):
13 def dfs(path, res):
14 if len(path) == len(digits):
15 res.append(''.join(path))
16 return
17
18 next_number = digits[len(path)]
19 for letter in KEYBOARD[next_number]:
20 path.append(letter)
21 dfs(path, res)
22 path.pop()
23
24 res = []
25 dfs([], res)
26 return res
27
1private static final Map<Character, char[]> KEYBOARD = Map.of(
2 '2', "abc".toCharArray(),
3 '3', "def".toCharArray(),
4 '4', "ghi".toCharArray(),
5 '5', "jkl".toCharArray(),
6 '6', "mno".toCharArray(),
7 '7', "pqrs".toCharArray(),
8 '8', "tuv".toCharArray(),
9 '9', "wxyz".toCharArray()
10);
11
12public static List<String> letterCombinationsOfPhoneNumber(String digits) {
13 List<String> res = new ArrayList<>();
14 dfs(new StringBuilder(), res, digits.toCharArray());
15 return res;
16}
17
18private static void dfs(StringBuilder path, List<String> res, char[] digits) {
19 if (path.length() == digits.length) {
20 res.add(path.toString());
21 return;
22 }
23 char next_digit = digits[path.length()];
24 for (char letter : KEYBOARD.get(next_digit)) {
25 path.append(letter);
26 dfs(path, res, digits);
27 path.deleteCharAt(path.length() - 1);
28 }
29}
30
1const KEYBOARD = {
2 '2': 'abc',
3 '3': 'def',
4 '4': 'ghi',
5 '5': 'jkl',
6 '6': 'mno',
7 '7': 'pqrs',
8 '8': 'tuv',
9 '9': 'wxyz',
10}
11
12function letter_combinations_of_phone_number(digits) {
13 let res = [];
14 dfs(digits, [], res);
15 return res;
16}
17
18function dfs(digits, path, res) {
19 if (path.length === digits.length) {
20 res.push(path.join(''));
21 return;
22 }
23 let next_number = digits.charAt(path.length);
24 for (let letter of KEYBOARD[next_number]) {
25 path.push(letter);
26 dfs(digits, path, res);
27 path.pop();
28 }
29}
30
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!