Shuffle the Array: Interleaving Two Halves in Place
LeetCode 1470. Shuffle the Array gives you an array of 2n elements in the form [x1, x2, ..., xn, y1, y2, ..., yn] and asks you to return the array in the form [x1, y1, x2, y2, ..., xn, yn]. In other words, interleave the first half and the second half like a perfect riffle shuffle with a deck of cards.
For example, given nums = [2, 5, 1, 3, 4, 7] and n = 3, the output is [2, 3, 5, 4, 1, 7]. The first half [2, 5, 1] and the second half [3, 4, 7] get zipped together into alternating positions.
Why this problem matters
Shuffle the Array is rated easy, and the code is short. But it teaches a pattern that comes up more often than you might expect: splitting an array into two logical halves and recombining them according to some rule. Variations of this idea appear in merge sort, partition-based algorithms, and problems that ask you to rearrange elements by index parity.
It is also a good warm-up for understanding how index arithmetic translates to array positions. The relationship result[2*i] = nums[i] and result[2*i + 1] = nums[i + n] is simple, but getting comfortable mapping between source and destination indices is a skill that pays off in harder problems.
The key insight
You do not need to think of this as "shuffling" at all. The problem is really just a zip operation. For each index i from 0 to n - 1, you want to place nums[i] and nums[i + n] next to each other in the result. That is one loop, two reads per iteration, and you are done.
The key observation is that element i from the first half goes to position 2 * i in the output, and element i + n from the second half goes to position 2 * i + 1. Once you see that mapping, the code writes itself.
The solution
def shuffle(nums: list[int], n: int) -> list[int]:
result = []
for i in range(n):
result.append(nums[i])
result.append(nums[i + n])
return result
The loop iterates n times. On each iteration, it grabs the next element from the first half (nums[i]) and the corresponding element from the second half (nums[i + n]), appending both to the result. After the loop, the result array contains all 2n elements interleaved in the correct order.
You can also write this as a list comprehension: [v for i in range(n) for v in (nums[i], nums[i + n])]. It does the same thing in one line. Both are valid, but the explicit loop is easier to explain in an interview.
Visual walkthrough
Let's trace through nums = [2, 5, 1, 3, 4, 7] with n = 3 to see exactly how the elements get paired and placed.
Step 1: Identify the two halves
The first n elements are x values. The second n elements are y values.
Step 2: Pair up x[i] with y[i]
Each x element pairs with the y element at the same offset: (x1,y1), (x2,y2), (x3,y3).
Step 3: Build the result by iterating i from 0 to n-1
For each i, append nums[i] then nums[i + n] to the result array.
Result: [2, 3, 5, 4, 1, 7]
Every even index holds an x value, every odd index holds a y value. Done in one pass.
Each iteration of the loop handles one pair. After three iterations, all six elements are in the result array in the correct interleaved order.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Single pass with new array | O(n) | O(n) |
Time: the loop runs n times, and each iteration does O(1) work (two appends). Total: O(n).
Space: we create a new result array of size 2n, so the extra space is O(n). Since the problem asks you to return a new array, this is the expected approach.
The building blocks
This problem breaks down into two reusable pieces that show up across many array problems:
1. Index mapping between source and destination
The core idea is computing where each element should go. Here, nums[i] maps to result[2*i] and nums[i + n] maps to result[2*i + 1]. This type of index arithmetic appears whenever you need to rearrange elements according to a formula rather than a comparison.
for i in range(n):
result[2 * i] = nums[i]
result[2 * i + 1] = nums[i + n]
2. Splitting an array into logical halves
Treating a single array as two separate halves based on an offset is a pattern you will see in merge sort, partition, and many divide-and-conquer problems. The first half is nums[0:n] and the second half is nums[n:2n]. No slicing is needed. You just use i and i + n as your two read pointers.
for i in range(n):
first_half_element = nums[i]
second_half_element = nums[i + n]
3. Zipping two sequences together
The interleaving pattern itself (take one from A, take one from B, repeat) is the same operation as Python's zip. Recognizing this lets you use built-in tools when appropriate.
result = []
for a, b in zip(nums[:n], nums[n:]):
result.extend([a, b])
Edge cases
- n = 1: the array has exactly two elements
[x1, y1]. The output is[x1, y1], unchanged. The loop runs once and appends both elements. - All elements are the same: if
nums = [5, 5, 5, 5]withn = 2, the output is[5, 5, 5, 5]. The algorithm does not depend on values being distinct. - Large n: with up to 500 elements (the constraint says
ncan be up to 500, so the array has up to 1000 elements), the O(n) solution handles it instantly. - Elements at the boundary:
nums[n-1]is the last element of the first half andnums[n]is the first element of the second half. They end up at positions2*(n-1)and2*0 + 1respectively, which is correct.
From understanding to recall
The code for this problem is about five lines. The logic is not complicated. But the index mapping (i to 2*i, i + n to 2*i + 1) is the kind of detail that fades if you do not practice it. Two weeks from now, when you see a problem that asks you to interleave or rearrange elements by position, you want the pattern to fire immediately.
That is what spaced repetition is for. You drill the index-mapping brick and the zip-two-halves brick as individual building blocks, typing them from scratch at increasing intervals. After a few cycles, the code is in your fingers, not just your head. CodeBricks breaks problems like this into their reusable components and schedules them so you build permanent recall.
Related posts
- Rotate Array - Another array rearrangement problem where index arithmetic determines where each element ends up
- Product of Array Except Self - An array problem that uses a two-pass technique to compute results based on surrounding elements
- Contains Duplicate - A foundational easy array problem that introduces the single-pass pattern with a hash set