Given an integer array arr[] of size n, where each element lies in the range [0, n-1], transform the array such that every element at index i becomes:
arr[i]=arr[arr[i]].
The transformation must be performed in-place, meaning the same array should store both the original and updated values without using another array.
Examples:
Input: arr[] = [1, 0]
Output: [0, 1]
Explanation: The original array is [1, 0].
At index 0, arr[0] = 1, so the new value becomes arr[1] = 0.
At index 1, arr[1] = 0, so the new value becomes arr[0] = 1.
Thus, the transformed array becomes [0, 1].Input: arr[] = [4, 0, 2, 1, 3]
Output: [3, 4, 2, 0, 1]
Explanation: The original array is [4, 0, 2, 1, 3].
Each element is replaced by the value at index arr[i] in the original array.
So the new values become 3, 4, 2, 0, 1 respectively, and the transformed array becomes [3, 4, 2, 0, 1].
[Expected Approach] Mathematical Encoding - O(n) Time and O(1) Space
The core idea is to store both the original value and the newly required value inside the exact same array spot so no extra memory is needed. Because all numbers in the array are strictly smaller than the array's size (n), we can use basic multiplication and remainders to mathematically pack two numbers into one. By updating each element to old_value + (new_value % n) * n, the array safely holds both states simultaneously. After encoding the entire array, dividing every element by n extracts just the newly rearranged values.
Algorithm:
- Store the total length of the array in a variable n.
- Loop through the array from start to finish.
- For each index i, find the value it needs to become (arr[arr[i]]). Use modulo % n to guarantee you retrieve the original state of that target, just in case it was already modified in an earlier step.
- Update the current element using the encoding formula: arr[i] = arr[i] + (arr[arr[i]] % n) * n.
- Run a final loop over the array, updating every element to arr[i] / n to strip away the old values and reveal the completed rearrangement.
Let's understand with an example:
Consider an array arr[] = [3, 2, 0, 1]
- i=0 : Target is arr[arr[0]] -> arr[3] -> 1. Pack it: arr[0] = 3 + (1 % 4) * 4 = 7. Array is now [7, 2, 0, 1].
- i=1 : Target is arr[arr[1]] -> arr[2] -> 0. Pack it: arr[1] = 2 + (0 % 4) * 4 = 2. Array is now [7, 2, 0, 1].
- i=2 : Target is arr[arr[2]] -> arr[0] -> 7. Original is 7 % 4 = 3. Pack it: arr[2] = 0 + (3 % 4) * 4 = 12. Array is now [7, 2, 12, 1].
- i=3 : Target is arr[arr[3]] -> arr[1] -> 2. Original is 2 % 4 = 2. Pack it: arr[3] = 1 + (2 % 4) * 4 = 9. Array is now [7, 2, 12, 9].
- Divide every element by n (4). 7/4=1, 2/4=0, 12/4=3, 9/4=2. Final Array: [1, 0, 3, 2].
#include <iostream>
#include <vector>
using namespace std;
void arrange(vector<int>& arr)
{
int n = arr.size();
// First step: Increase all values
// by (arr[arr[i]]%n)*n
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (int i = 0; i < n; i++)
arr[i] /= n;
}
void printArr(vector<int>& arr)
{
int n = arr.size();
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
}
int main()
{
vector<int> arr = {3, 2, 0, 1};
arrange(arr);
printArr(arr);
return 0;
}
import java.util.*;
class GFG {
public void arrange(int[] arr)
{
int n = arr.length;
// First step: Increase all values
// by (arr[arr[i]]%n)*n
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (int i = 0; i < n; i++)
arr[i] /= n;
}
static void printArr(int[] arr)
{
int n = arr.length;
for (int i = 0; i < n; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
public static void main(String[] args)
{
int[] arr = { 3, 2, 0, 1 };
arrange(arr);
printArr(arr);
}
}
def arrange(arr):
n = len(arr)
# First step: Increase all values
# by (arr[arr[i]]%n)*n
for i in range(n):
arr[i] += (arr[arr[i]] % n) * n
# Second Step: Divide all values by n
for i in range(n):
arr[i] //= n
def printArr(arr):
n = len(arr)
for i in range(n):
print(arr[i], end=' ')
print()
if __name__ == '__main__':
arr = [3, 2, 0, 1]
arrange(arr)
printArr(arr)
using System;
using System.Collections.Generic;
class GFG{
public void arrange(int[] arr) {
int n = arr.Length;
// First step: Increase all values
// by (arr[arr[i]]%n)*n
for (int i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (int i = 0; i < n; i++)
arr[i] /= n;
}
public void PrintArr(int[] arr) {
int n = arr.Length;
for (int i = 0; i < n; i++)
Console.Write(arr[i] + " ");
Console.WriteLine();
}
public void Main() {
int[] arr = { 3, 2, 0, 1 };
arrange(arr);
PrintArr(arr);
}
}
function arrange(arr)
{
const n = arr.length;
// First step: Increase all values
// by (arr[arr[i]]%n)*n
for (let i = 0; i < n; i++)
arr[i] += (arr[arr[i]] % n) * n;
// Second Step: Divide all values by n
for (let i = 0; i < n; i++)
arr[i] = Math.floor(arr[i] / n);
}
function printArr(arr)
{
const n = arr.length;
for (let i = 0; i < n; i++)
process.stdout.write(arr[i] + " ");
console.log();
}
const arr = [ 3, 2, 0, 1 ];
arrange(arr);
printArr(arr);
Output
3 2 0 1