Geek starts with an array of length 2n - 1 indexed from 1 to 2n - 1. Initially, for every i (1 âĪ i âĪ n), the value i is placed at index 2i - 1, and all other positions are empty. Geek repeatedly performs the following operation:
- Select the non-empty cell with the largest index.
- Move its value to the nearest empty cell on its left.
He continues performing this operation until the first n positions of the array become completely filled. The figure below illustrates the process for n = 4.Â

Given an array queries[] containing q indices, return the elements present at those indices in the final array after all operations are completed.
Examples:
Input: n = 4, queries[] = [2, 3, 4]
Output: [3, 2, 4]
Explanation: After performing all operations, the final array becomes: [1, 3, 2, 4]. Therefore, the elements at indices 2, 3, and 4 are 3, 2, and 4 respectively.Input: n = 13, queries[] = [10, 5, 4, 8]
Output: [13, 3, 8, 9]
Explanation: After performing all operations, the final array becomes: [1, 12, 2, 8, 3, 11, 4, 9, 5, 13, 6, 10, 7]. Therefore, the elements at indices 10, 5, 4, and 8 are 13, 3, 8, and 9 respectively.
Table of Content
[Naive Approach] Array Simulation - O(nÂē) Time and O(n) Space
Place numbers 1 to n at odd positions. Repeatedly shift rightmost occupied element to nearest empty cell on its left until first n cells are filled. Return values at query positions.
- Create array of size 2n initialized to 0
- Place i at position 2i-1 for i from 1 to n
- While first n cells not all filled
- Find rightmost occupied cell
- Find nearest empty cell to its left
- Move occupied value to empty cell
- Answer queries from array
#include <bits/stdc++.h>
using namespace std;
vector<int> findElements(int n, vector<int>& queries) {
vector<int> arr(2 * n, 0);
// Initially place elements at odd indices (1-based indexing)
for (int i = 1; i <= n; i++)
arr[2 * i - 1] = i;
// Simulate the shifting process
while (true) {
bool complete = true;
for (int i = 1; i <= n; i++) {
if (arr[i] == 0) {
complete = false;
break;
}
}
if (complete)
break;
// Find the rightmost occupied cell
int occupied = -1;
for (int i = 2 * n - 1; i >= 1; i--) {
if (arr[i] != 0) {
occupied = i;
break;
}
}
// Find nearest empty cell on its left
int empty = occupied - 1;
while (empty >= 1 && arr[empty] != 0)
empty--;
arr[empty] = arr[occupied];
arr[occupied] = 0;
}
vector<int> ans;
for (int idx : queries)
ans.push_back(arr[idx]);
return ans;
}
int main() {
int n = 4;
vector<int> queries = {2, 3, 4};
vector<int> ans = findElements(n, queries);
for (int x : ans)
cout << x << " ";
return 0;
}
import java.util.ArrayList;
class GFG {
public static ArrayList<Integer> findElements(int n, int[] queries) {
int[] arr = new int[2 * n];
// Initially place elements at odd indices (1-based indexing)
for (int i = 1; i <= n; i++) {
arr[2 * i - 1] = i;
}
// Simulate the shifting process
while (true) {
boolean complete = true;
for (int i = 1; i <= n; i++) {
if (arr[i] == 0) {
complete = false;
break;
}
}
if (complete)
break;
// Find the rightmost occupied cell
int occupied = -1;
for (int i = 2 * n - 1; i >= 1; i--) {
if (arr[i] != 0) {
occupied = i;
break;
}
}
// Find nearest empty cell on its left
int empty = occupied - 1;
while (empty >= 1 && arr[empty] != 0) {
empty--;
}
arr[empty] = arr[occupied];
arr[occupied] = 0;
}
ArrayList<Integer> ans = new ArrayList<>();
for (int idx : queries) {
ans.add(arr[idx]);
}
return ans;
}
public static void main(String[] args) {
int n = 4;
int[] queries = {2, 3, 4};
ArrayList<Integer> ans = findElements(n, queries);
for (int x : ans) {
System.out.print(x + " ");
}
}
}
def findElements(n, queries):
arr = [0] * (2 * n)
# Initially place elements at odd indices (1-based indexing)
for i in range(1, n + 1):
arr[2 * i - 1] = i
# Simulate the shifting process
while True:
complete = True
for i in range(1, n + 1):
if arr[i] == 0:
complete = False
break
if complete:
break
# Find the rightmost occupied cell
occupied = -1
for i in range(2 * n - 1, 0, -1):
if arr[i] != 0:
occupied = i
break
# Find nearest empty cell on its left
empty = occupied - 1
while empty >= 1 and arr[empty] != 0:
empty -= 1
arr[empty] = arr[occupied]
arr[occupied] = 0
ans = []
for idx in queries:
ans.append(arr[idx])
return ans
if __name__ == "__main__":
n = 4
queries = [2, 3, 4]
ans = findElements(n, queries)
print(' '.join(map(str, ans)))
using System;
using System.Collections.Generic;
class GfG {
public static List<int> findElements(int n, int[] queries) {
int[] arr = new int[2 * n];
// Initially place elements at odd indices (1-based indexing)
for (int i = 1; i <= n; i++) {
arr[2 * i - 1] = i;
}
// Simulate the shifting process
while (true) {
bool complete = true;
for (int i = 1; i <= n; i++) {
if (arr[i] == 0) {
complete = false;
break;
}
}
if (complete)
break;
// Find the rightmost occupied cell
int occupied = -1;
for (int i = 2 * n - 1; i >= 1; i--) {
if (arr[i] != 0) {
occupied = i;
break;
}
}
// Find nearest empty cell on its left
int empty = occupied - 1;
while (empty >= 1 && arr[empty] != 0) {
empty--;
}
arr[empty] = arr[occupied];
arr[occupied] = 0;
}
List<int> ans = new List<int>();
foreach (int idx in queries) {
ans.Add(arr[idx]);
}
return ans;
}
static void Main(string[] args) {
int n = 4;
int[] queries = {2, 3, 4};
List<int> ans = findElements(n, queries);
foreach (int x in ans) {
Console.Write(x + " ");
}
}
}
function findElements(n, queries) {
let arr = new Array(2 * n).fill(0);
// Initially place elements at odd indices (1-based indexing)
for (let i = 1; i <= n; i++) {
arr[2 * i - 1] = i;
}
// Simulate the shifting process
while (true) {
let complete = true;
for (let i = 1; i <= n; i++) {
if (arr[i] === 0) {
complete = false;
break;
}
}
if (complete)
break;
// Find the rightmost occupied cell
let occupied = -1;
for (let i = 2 * n - 1; i >= 1; i--) {
if (arr[i] !== 0) {
occupied = i;
break;
}
}
// Find nearest empty cell on its left
let empty = occupied - 1;
while (empty >= 1 && arr[empty] !== 0) {
empty--;
}
arr[empty] = arr[occupied];
arr[occupied] = 0;
}
let ans = [];
for (let idx of queries) {
ans.push(arr[idx]);
}
return ans;
}
// Driver code
const n = 4;
const queries = [2, 3, 4];
const ans = findElements(n, queries);
console.log(ans.join(' '));
Output
3 2 4
[Expected Approach] Recursive Position Mapping - O(n log n) Time and O(log n) Space
The key observation is that the odd positions in the final array always contain the smallest ân/2â numbers in increasing order, so their values can be found directly. For an even position, compress the even indices into consecutive positions (2 -> 1, 4 -> 2, ...). These compressed positions form the same problem for ân/2â elements, so solve it recursively and add an offset of (n + 1) / 2 to get the actual value. If n is odd, adjust the compressed position before making the recursive call.
- If the queried index is odd, return (idx + 1) / 2.
- Otherwise, compress the even index using pos = idx / 2.
- Recursively find the corresponding element for the smaller problem of size n / 2.
- Add an offset of (n + 1) / 2 to obtain the actual value.
- If n is odd, adjust the compressed position before the recursive call to account for the cyclic shift.
Consider n = 4 and queries[] = [2, 3, 4].
The final array after all the shifts is: [1, 3, 2, 4], Instead of constructing this array, the recursive function directly computes the value at each queried index.
Query: idx = 2, Since 2 is an even index, we solve it recursively.
- half = 4 / 2 = 2, pos = 2 / 2 = 1, offset = (4 + 1) / 2 = 2
- As n is even: findElement(4, 2) = 2 + findElement(2, 1)
- Now 1 is an odd index, so: findElement(2, 1) = (1 + 1) / 2 = 1. Therefore, findElement(4, 2) = 2 + 1 = 3
Query: idx = 3, Since 3 is an odd index, its value is obtained directly. findElement(4, 3) = (3 + 1) / 2 = 2
Query: idx = 4, Since 4 is an even index:
- half = 2, pos = 2, offset = 2
- Recurse on the smaller problem: findElement(4, 4) = 2 + findElement(2, 2)
- Again, 2 is even: half = 1, pos = 1, offset = 1
- findElement(2, 2) = 1 + findElement(1, 1)
- Now 1 is odd: findElement(1, 1) = 1
- Returning back: findElement(2, 2) = 1 + 1 = 2, findElement(4, 4) = 2 + 2 = 4
Final Answer:
- Query 2 -> 3, Query 3 -> 2, Query 4 -> 4
- Hence, the output is: [3, 2, 4]
#include <bits/stdc++.h>
using namespace std;
int findElement(int n, int idx) {
// Odd positions directly contain the smallest numbers
if (idx & 1)
return (idx + 1) / 2;
int half = n / 2;
int pos = idx / 2;
int offset = (n + 1) / 2;
// Recur on compressed even positions
if (n & 1) {
if (pos == 1)
return offset + findElement(half, half);
return offset + findElement(half, pos - 1);
}
return offset + findElement(half, pos);
}
vector<int> findElements(int n, vector<int>& queries) {
vector<int> ans;
for (int idx : queries)
ans.push_back(findElement(n, idx));
return ans;
}
int main() {
int n = 4;
vector<int> queries = {2, 3, 4};
vector<int> ans = findElements(n, queries);
for (int x : ans)
cout << x << " ";
return 0;
}
import java.util.ArrayList;
class GfG {
public static int findElement(int n, int idx) {
// Odd positions directly contain the smallest numbers
if ((idx & 1) == 1) {
return (idx + 1) / 2;
}
int half = n / 2;
int pos = idx / 2;
int offset = (n + 1) / 2;
// Recur on compressed even positions
if ((n & 1) == 1) {
if (pos == 1) {
return offset + findElement(half, half);
}
return offset + findElement(half, pos - 1);
}
return offset + findElement(half, pos);
}
public static ArrayList<Integer> findElements(int n, int[] queries) {
ArrayList<Integer> ans = new ArrayList<>();
for (int idx : queries) {
ans.add(findElement(n, idx));
}
return ans;
}
public static void main(String[] args) {
int n = 4;
int[] queries = {2, 3, 4};
ArrayList<Integer> ans = findElements(n, queries);
for (int x : ans) {
System.out.print(x + " ");
}
}
}
def findElement(n, idx):
# Odd positions directly contain the smallest numbers
if idx & 1:
return (idx + 1) // 2
half = n // 2
pos = idx // 2
offset = (n + 1) // 2
# Recur on compressed even positions
if n & 1:
if pos == 1:
return offset + findElement(half, half)
return offset + findElement(half, pos - 1)
return offset + findElement(half, pos)
def findElements(n, queries):
ans = []
for idx in queries:
ans.append(findElement(n, idx))
return ans
if __name__ == "__main__":
n = 4
queries = [2, 3, 4]
ans = findElements(n, queries)
print(' '.join(map(str, ans)))
using System;
using System.Collections.Generic;
class GfG {
public static int findElement(int n, int idx) {
// Odd positions directly contain the smallest numbers
if ((idx & 1) == 1) {
return (idx + 1) / 2;
}
int half = n / 2;
int pos = idx / 2;
int offset = (n + 1) / 2;
// Recur on compressed even positions
if ((n & 1) == 1) {
if (pos == 1) {
return offset + findElement(half, half);
}
return offset + findElement(half, pos - 1);
}
return offset + findElement(half, pos);
}
public static List<int> findElements(int n, int[] queries) {
List<int> ans = new List<int>();
foreach (int idx in queries) {
ans.Add(findElement(n, idx));
}
return ans;
}
static void Main(string[] args) {
int n = 4;
int[] queries = {2, 3, 4};
List<int> ans = findElements(n, queries);
foreach (int x in ans) {
Console.Write(x + " ");
}
}
}
function findElement(n, idx) {
// Odd positions directly contain the smallest numbers
if (idx & 1) {
return Math.floor((idx + 1) / 2);
}
let half = Math.floor(n / 2);
let pos = Math.floor(idx / 2);
let offset = Math.floor((n + 1) / 2);
// Recur on compressed even positions
if (n & 1) {
if (pos === 1) {
return offset + findElement(half, half);
}
return offset + findElement(half, pos - 1);
}
return offset + findElement(half, pos);
}
function findElements(n, queries) {
let ans = [];
for (let idx of queries) {
ans.push(findElement(n, idx));
}
return ans;
}
// Driver code
const n = 4;
const queries = [2, 3, 4];
const ans = findElements(n, queries);
console.log(ans.join(' '));
Output
3 2 4