Given an array arr[] of n elements in the form {a1, a2, a3, ..., a(n/2), b1, b2, b3, ..., b(n/2)}, rearrange the array in place to {a1, b1, a2, b2, a3, b3, ..., a(n/2), b(n/2)} without using extra space.
Note: n is always even.
Examples:
Input: arr[] = [1, 2, 9, 15]
Output: [1, 9, 2, 15]
Explanation: Here a1 = 1, a2 = 2, b1 = 9, b2 = 15. The final array becomes a1, b1, a2, b2 = [1, 9, 2, 15].Input: arr[] = [1, 2, 3, 4, 5, 6]
Output: [1, 4, 2, 5, 3, 6]
Explanation: Here a1 = 1, a2 = 2, a3 = 3, b1 = 4, b2 = 5, b3 = 6. The final array becomes a1, b1, a2, b2, a3, b3 = [1, 4, 2, 5, 3, 6].
Table of Content
[Naive Approach] Using Extra Array - O(n) Time and O(n) Space
The most direct idea is to build the interleaved sequence in a separate array, alternating between picking the next value from the first half and the next value from the second half, then copying the result back. This works correctly but doesn't satisfy the requirement of using no extra space.
- Split the array conceptually into its first half and second half.
- Build a new array by alternately taking one element from the first half and one from the second half.
- Copy the new array's values back into the original array.
#include <iostream>
#include <vector>
using namespace std;
void shuffleArray(vector<int>& arr) {
int n = arr.size();
vector<int> res;
int half = n / 2;
// Alternately pick from the first half and the second half
for (int i = 0; i < half; i++) {
res.push_back(arr[i]);
res.push_back(arr[half + i]);
}
// Copy the interleaved result back into the original array
for (int i = 0; i < n; i++)
arr[i] = res[i];
}
// driver code
int main() {
vector<int> arr = {1, 2, 9, 15};
shuffleArray(arr);
for (int x : arr)
cout << x << " ";
cout << endl;
return 0;
}
import java.util.*;
class GfG {
static void shuffleArray(int[] arr) {
int n = arr.length;
int[] res = new int[n];
int half = n / 2;
// Alternately pick from the first half and the second half
int idx = 0;
for (int i = 0; i < half; i++) {
res[idx++] = arr[i];
res[idx++] = arr[half + i];
}
// Copy the interleaved result back into the original array
for (int i = 0; i < n; i++)
arr[i] = res[i];
}
public static void main(String[] args) {
int[] arr = {1, 2, 9, 15};
shuffleArray(arr);
for (int x : arr)
System.out.print(x + " ");
System.out.println();
}
}
def shuffleArray(arr):
n = len(arr)
res = []
half = n // 2
# Alternately pick from the first half and the second half
for i in range(half):
res.append(arr[i])
res.append(arr[half + i])
# Copy the interleaved result back into the original array
for i in range(n):
arr[i] = res[i]
if __name__ == "__main__":
arr = [1, 2, 9, 15]
shuffleArray(arr)
print(" ".join(map(str, arr)))
using System;
class GfG {
static void shuffleArray(int[] arr) {
int n = arr.Length;
int[] res = new int[n];
int half = n / 2;
// Alternately pick from the first half and the second half
int idx = 0;
for (int i = 0; i < half; i++) {
res[idx++] = arr[i];
res[idx++] = arr[half + i];
}
// Copy the interleaved result back into the original array
for (int i = 0; i < n; i++)
arr[i] = res[i];
}
static void Main() {
int[] arr = {1, 2, 9, 15};
shuffleArray(arr);
foreach (int x in arr)
Console.Write(x + " ");
Console.WriteLine();
}
}
function shuffleArray(arr) {
let n = arr.length;
let res = [];
let half = Math.floor(n / 2);
// Alternately pick from the first half and the second half
for (let i = 0; i < half; i++) {
res.push(arr[i]);
res.push(arr[half + i]);
}
// Copy the interleaved result back into the original array
for (let i = 0; i < n; i++)
arr[i] = res[i];
}
// driver code
let arr = [1, 2, 9, 15];
shuffleArray(arr);
console.log(arr.join(" "));
Output
1 9 2 15
[Expected Approach] Using Bit Manipulation - O(n) Time and O(1) Space
Since every value fits within 10 bits, two values can be temporarily packed into a single array cell using bit shifts - the first half's value in the lower bits and the second half's value in the upper bits. Once every cell in the second half holds a packed pair, unpacking them in order naturally produces the interleaved arrangement, all without needing any extra storage.
- Pack each value from the first half into the upper 10 bits of its paired value in the second half, working from the end of the array backward so values aren't overwritten before they're used.
- Once every second-half cell holds a packed pair, walk through them in order, extracting the lower 10 bits and the upper bits from each cell.
- Place the two extracted values into their correct interleaved positions at the front of the array, advancing two positions at a time.
#include <iostream>
#include <vector>
using namespace std;
void shuffleArray(vector<int>& arr) {
int n = arr.size();
// Pack each first-half value into the upper bits of its paired second-half slot
int i = n / 2 - 1;
for (int j = n - 1; j >= n / 2; j--) {
arr[j] = (arr[j] << 10) | arr[i];
i--;
}
// Unpack both values from each combined cell into their final interleaved order
i = 0;
for (int j = n / 2; j < n; j++) {
int num1 = arr[j] & 1023;
int num2 = arr[j] >> 10;
arr[i] = num1;
arr[i + 1] = num2;
i += 2;
}
}
int main() {
vector<int> arr = {1, 2, 9, 15};
shuffleArray(arr);
for (int x : arr)
cout << x << " ";
cout << endl;
return 0;
}
import java.util.*;
class GfG {
static void shuffleArray(int[] arr) {
int n = arr.length;
// Pack each first-half value into the upper bits of its paired second-half slot
int i = n / 2 - 1;
for (int j = n - 1; j >= n / 2; j--) {
arr[j] = (arr[j] << 10) | arr[i];
i--;
}
// Unpack both values from each combined cell into their final interleaved order
i = 0;
for (int j = n / 2; j < n; j++) {
int num1 = arr[j] & 1023;
int num2 = arr[j] >> 10;
arr[i] = num1;
arr[i + 1] = num2;
i += 2;
}
}
public static void main(String[] args) {
int[] arr = {1, 2, 9, 15};
shuffleArray(arr);
for (int x : arr)
System.out.print(x + " ");
System.out.println();
}
}
def shuffleArray(arr):
n = len(arr)
# Pack each first-half value into the upper bits of its paired second-half slot
i = n // 2 - 1
for j in range(n - 1, n // 2 - 1, -1):
arr[j] = (arr[j] << 10) | arr[i]
i -= 1
# Unpack both values from each combined cell into their final interleaved order
i = 0
for j in range(n // 2, n):
num1 = arr[j] & 1023
num2 = arr[j] >> 10
arr[i] = num1
arr[i + 1] = num2
i += 2
if __name__ == "__main__":
arr = [1, 2, 9, 15]
shuffleArray(arr)
print(" ".join(map(str, arr)))
using System;
class GfG {
static void shuffleArray(int[] arr) {
int n = arr.Length;
// Pack each first-half value into the upper bits of its paired second-half slot
int i = n / 2 - 1;
for (int j = n - 1; j >= n / 2; j--) {
arr[j] = (arr[j] << 10) | arr[i];
i--;
}
// Unpack both values from each combined cell into their final interleaved order
i = 0;
for (int j = n / 2; j < n; j++) {
int num1 = arr[j] & 1023;
int num2 = arr[j] >> 10;
arr[i] = num1;
arr[i + 1] = num2;
i += 2;
}
}
static void Main() {
int[] arr = {1, 2, 9, 15};
shuffleArray(arr);
foreach (int x in arr)
Console.Write(x + " ");
Console.WriteLine();
}
}
function shuffleArray(arr) {
let n = arr.length;
// Pack each first-half value into the upper bits of its paired second-half slot
let i = Math.floor(n / 2) - 1;
for (let j = n - 1; j >= Math.floor(n / 2); j--) {
arr[j] = (arr[j] << 10) | arr[i];
i--;
}
// Unpack both values from each combined cell into their final interleaved order
i = 0;
for (let j = Math.floor(n / 2); j < n; j++) {
let num1 = arr[j] & 1023;
let num2 = arr[j] >> 10;
arr[i] = num1;
arr[i + 1] = num2;
i += 2;
}
}
// driver code
let arr = [1, 2, 9, 15];
shuffleArray(arr);
console.log(arr.join(" "));
Output
1 9 2 15