Given an array arr[], perform the following operations.
- Sort all elements at even indices in increasing order and all elements at odd indices in decreasing order.
- Construct the final array by placing all sorted even-indexed elements first, followed by all sorted odd-indexed elements in decreasing order.
Examples:
Input: arr[] = [1, 8, 2, 3, 4, 5, 6, 7]
Output: [1, 2, 4, 6, 8, 7, 5, 3]
Explanation: Even-indexed elements are 1, 2, 4, 6, which after sorting become 1, 2, 4, 6. Odd-indexed elements are 8, 3, 5, 7, which after sorting in decreasing order become 8, 7, 5, 3. The final array is formed by placing the sorted even-indexed elements first, followed by the sorted odd-indexed elements.Input: arr[] = [3, 1, 2, 4, 5, 9, 13, 14, 12]
Output: [2, 3, 5, 12, 13, 14, 9, 4, 1]
Explanation: Even-indexed elements are 3, 2, 5, 13, 12, which after sorting become 2, 3, 5, 12, 13. Odd-indexed elements are 1, 4, 9, 14, which after sorting in decreasing order become 14, 9, 4, 1. The final array is formed by placing the sorted even-indexed elements first, followed by the sorted odd-indexed elements.
Table of Content
- [Naive Approach] Separate Even and Odd Indexed Elements and Sort - O(n log n) Time and O(n) Space
- [Expected Approach] Reverse Odd Indexed Elements and Sort Both Halves - O(n log n) Time and O(1) Space
- [Alternate Approach] Negate Even Indexed Elements and Rearrange After Sorting - O(n log n) Time and O(1) Space
[Naive Approach] Separate Even and Odd Indexed Elements and Sort - O(n log n) Time and O(n) Space
The idea is to create two auxiliary arrays evenArr[] and oddArr[] respectively. We traverse input array and put all even-placed elements in evenArr[] and odd placed elements in oddArr[]. Then we sort evenArr[] in ascending and oddArr[] in descending order. Finally, copy evenArr[] and oddArr[] to get the required result.
#include <iostream>
#include <vector>
using namespace std;
vector<int> bitonicGenerator(vector<int> &arr)
{
// Create arrays to store elements at even
// and odd indices.
vector<int> evenArr;
vector<int> oddArr;
// Put elements into evenArr[] and oddArr[]
// according to their positions.
for (int i = 0; i < arr.size(); i++)
{
if (i % 2 == 0)
evenArr.push_back(arr[i]);
else
oddArr.push_back(arr[i]);
}
// Sort even indexed elements in ascending order.
sort(evenArr.begin(), evenArr.end());
// Sort odd indexed elements in descending order.
sort(oddArr.begin(), oddArr.end(), greater<int>());
int idx = 0;
// Copy all even indexed elements first.
for (int i = 0; i < evenArr.size(); i++)
arr[idx++] = evenArr[i];
// Copy all odd indexed elements next.
for (int i = 0; i < oddArr.size(); i++)
arr[idx++] = oddArr[i];
return arr;
}
int main()
{
vector<int> arr = {3, 1, 2, 4, 5, 9, 13, 14, 12};
vector<int> res = bitonicGenerator(arr);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i != res.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.*;
class GFG {
static ArrayList<Integer> bitonicGenerator(int[] arr)
{
// Create arrays to store elements at even
// and odd indices.
ArrayList<Integer> evenArr = new ArrayList<>();
ArrayList<Integer> oddArr = new ArrayList<>();
// Put elements into evenArr[] and oddArr[]
// according to their positions.
for (int i = 0; i < arr.length; i++) {
if (i % 2 == 0)
evenArr.add(arr[i]);
else
oddArr.add(arr[i]);
}
// Sort even indexed elements in ascending order.
Collections.sort(evenArr);
// Sort odd indexed elements in descending order.
Collections.sort(oddArr,
Collections.reverseOrder());
ArrayList<Integer> res = new ArrayList<>();
// Copy all even indexed elements first.
for (int i = 0; i < evenArr.size(); i++)
res.add(evenArr.get(i));
// Copy all odd indexed elements next.
for (int i = 0; i < oddArr.size(); i++)
res.add(oddArr.get(i));
return res;
}
public static void main(String[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
ArrayList<Integer> res = bitonicGenerator(arr);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i != res.size() - 1)
System.out.print(", ");
}
System.out.println("]");
}
}
def bitonicGenerator(arr):
# Create arrays to store elements at even
# and odd indices.
evenArr = []
oddArr = []
# Put elements into evenArr[] and oddArr[]
# according to their positions.
for i in range(len(arr)):
if i % 2 == 0:
evenArr.append(arr[i])
else:
oddArr.append(arr[i])
# Sort even indexed elements in ascending order.
evenArr.sort()
# Sort odd indexed elements in descending order.
oddArr.sort(reverse=True)
idx = 0
# Copy all even indexed elements first.
for i in range(len(evenArr)):
arr[idx] = evenArr[i]
idx += 1
# Copy all odd indexed elements next.
for i in range(len(oddArr)):
arr[idx] = oddArr[i]
idx += 1
return arr
if __name__ == '__main__':
arr = [3, 1, 2, 4, 5, 9, 13, 14, 12]
res = bitonicGenerator(arr)
print('[', end='')
for i in range(len(res)):
print(res[i], end='' if i == len(res) - 1 else ', ')
print(']')
using System;
using System.Collections.Generic;
class GFG {
static List<int> bitonicGenerator(int[] arr)
{
// Create arrays to store elements at even
// and odd indices.
List<int> evenArr = new List<int>();
List<int> oddArr = new List<int>();
// Put elements into evenArr[] and oddArr[]
// according to their positions.
for (int i = 0; i < arr.Length; i++) {
if (i % 2 == 0)
evenArr.Add(arr[i]);
else
oddArr.Add(arr[i]);
}
// Sort even indexed elements in ascending order.
evenArr.Sort();
// Sort odd indexed elements in descending order.
oddArr.Sort();
oddArr.Reverse();
List<int> res = new List<int>();
// Copy all even indexed elements first.
for (int i = 0; i < evenArr.Count; i++)
res.Add(evenArr[i]);
// Copy all odd indexed elements next.
for (int i = 0; i < oddArr.Count; i++)
res.Add(oddArr[i]);
return res;
}
static void Main(string[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
List<int> res = bitonicGenerator(arr);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i != res.Count - 1)
Console.Write(", ");
}
Console.WriteLine("]");
}
}
function bitonicGenerator(arr)
{
// Create arrays to store elements at even
// and odd indices.
let evenArr = [];
let oddArr = [];
// Put elements into evenArr[] and oddArr[]
// according to their positions.
for (let i = 0; i < arr.length; i++) {
if (i % 2 === 0)
evenArr.push(arr[i]);
else
oddArr.push(arr[i]);
}
// Sort even indexed elements in ascending order.
evenArr.sort((a, b) => a - b);
// Sort odd indexed elements in descending order.
oddArr.sort((a, b) => b - a);
let idx = 0;
// Copy all even indexed elements first.
for (let i = 0; i < evenArr.length; i++)
arr[idx++] = evenArr[i];
// Copy all odd indexed elements next.
for (let i = 0; i < oddArr.length; i++)
arr[idx++] = oddArr[i];
return arr;
}
// Driver Code
let arr = [ 3, 1, 2, 4, 5, 9, 13, 14, 12 ];
let res = bitonicGenerator(arr);
console.log("[");
for (let i = 0; i < res.length; i++) {
console.log(res[i]);
if (i !== res.length - 1)
console.log(", ");
}
console.log("]");
Output
[2, 3, 5, 12, 13, 14, 9, 4, 1]
[Expected Approach] Reverse Odd Indexed Elements and Sort Both Halves - O(n log n) Time and O(1) Space
The idea is to swap the first half odd index positions with the second half even index positions. This ensures that all even index elements become contiguous in the first half and remaining in the second half. Now we need to simply sort the first half in increasing order and the second half in decreasing order.
Let us understand with an example arr[] = [3, 1, 2, 4, 5, 9, 13, 14, 12]
- After swapping the first half odd positions with the second half even positions [3 12 2 13 5 9 4 14 1]
- After Sorting the first half in ascending order [2, 3, 5, 12, 13, 9, 4, 14, 1]
- After sorting the second half in descending order: arr[] = [2, 3, 5, 12, 13, 14, 9, 4, 1]
#include <bits/stdc++.h>
using namespace std;
vector<int> bitonicGenerator(vector<int> &arr)
{
// First odd index.
int i = 1;
// Last index.
int n = arr.size();
int j = n - 1;
// If last index is odd,
// decrement j to even index.
if (j % 2 != 0)
j--;
// Swap odd indexed elements from
// both ends until the middle.
while (i < j)
{
swap(arr[i], arr[j]);
i += 2;
j -= 2;
}
// Sort first half in ascending order.
sort(arr.begin(), arr.begin() + (n + 1) / 2);
// Sort second half in descending order.
sort(arr.begin() + (n + 1) / 2, arr.end(), greater<int>());
return arr;
}
int main()
{
vector<int> arr = {3, 1, 2, 4, 5, 9, 13, 14, 12};
vector<int> res = bitonicGenerator(arr);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i != res.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.*;
class GFG {
static ArrayList<Integer> bitonicGenerator(int[] arr)
{
// First odd index.
int i = 1;
// Last index.
int n = arr.length;
int j = n - 1;
// If last index is odd,
// decrement j to even index.
if (j % 2 != 0)
j--;
// Swap odd indexed elements from
// both ends until the middle.
while (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i += 2;
j -= 2;
}
// Sort first half in ascending order.
Arrays.sort(arr, 0, (n + 1) / 2);
// Sort second half in ascending order first.
Arrays.sort(arr, (n + 1) / 2, n);
// Reverse second half to make it descending.
int left = (n + 1) / 2;
int right = n - 1;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
ArrayList<Integer> res = new ArrayList<>();
for (int x : arr)
res.add(x);
return res;
}
public static void main(String[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
ArrayList<Integer> res = bitonicGenerator(arr);
System.out.print("[");
for (int k = 0; k < res.size(); k++) {
System.out.print(res.get(k));
if (k != res.size() - 1)
System.out.print(", ");
}
System.out.println("]");
}
}
from typing import List
def bitonicGenerator(arr: List[int]) -> List[int]:
# First odd index.
i = 1
# Last index.
n = len(arr)
j = n - 1
# If last index is odd,
# decrement j to even index.
if j % 2 != 0:
j -= 1
# Swap odd indexed elements from
# both ends until the middle.
while i < j:
arr[i], arr[j] = arr[j], arr[i]
i += 2
j -= 2
# Sort first half in ascending order.
arr[:(n + 1) // 2] = sorted(arr[:(n + 1) // 2])
# Sort second half in descending order.
arr[(n + 1) // 2:] = sorted(arr[(n + 1) // 2:], reverse=True)
return arr
if __name__ == "__main__":
arr = [3, 1, 2, 4, 5, 9, 13, 14, 12]
res = bitonicGenerator(arr)
print("[" + ", ".join(map(str, res)) + "]")
using System;
using System.Collections.Generic;
class GFG {
static List<int> bitonicGenerator(int[] arr)
{
// First odd index.
int i = 1;
// Last index.
int n = arr.Length;
int j = n - 1;
// If last index is odd,
// decrement j to even index.
if (j % 2 != 0)
j--;
// Swap odd indexed elements from
// both ends until the middle.
while (i < j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i += 2;
j -= 2;
}
// Sort first half in ascending order.
Array.Sort(arr, 0, (n + 1) / 2);
// Sort second half in ascending order first.
Array.Sort(arr, (n + 1) / 2, n - (n + 1) / 2);
// Reverse second half to make it descending.
Array.Reverse(arr, (n + 1) / 2, n - (n + 1) / 2);
List<int> res = new List<int>();
foreach(int x in arr) res.Add(x);
return res;
}
static void Main(string[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
List<int> res = bitonicGenerator(arr);
Console.Write("[");
for (int k = 0; k < res.Count; k++) {
Console.Write(res[k]);
if (k != res.Count - 1)
Console.Write(", ");
}
Console.WriteLine("]");
}
}
// Function to generate a bitonic sequence.
function bitonicGenerator(arr)
{
// First odd index.
let i = 1;
// Last index.
let n = arr.length;
let j = n - 1;
// If last index is odd,
// decrement j to even index.
if (j % 2 !== 0)
j--;
// Swap odd indexed elements from
// both ends until the middle.
while (i < j) {
[arr[i], arr[j]] = [ arr[j], arr[i] ];
i += 2;
j -= 2;
}
// Sort first half in ascending order.
let firstHalf = arr.slice(0, Math.floor((n + 1) / 2))
.sort((a, b) => a - b);
// Sort second half in descending order.
let secondHalf = arr.slice(Math.floor((n + 1) / 2))
.sort((a, b) => b - a);
return [...firstHalf, ...secondHalf ];
}
// Driver Code
let arr = [ 3, 1, 2, 4, 5, 9, 13, 14, 12 ];
let res = bitonicGenerator(arr);
console.log(res);
Output
[2, 3, 5, 12, 13, 14, 9, 4, 1]
[Alternate Approach] Negate Even Indexed Elements and Rearrange After Sorting - O(n log n) Time and O(1) Space
Another efficient approach to solve the problem in O(1) auxiliary space is by Using negative multiplication.
The idea is to negate the elements at even indices so that after sorting the entire array, these elements automatically move to the beginning. Then, restore their original values and reverse both halves separately to arrange the first half in ascending order and the second half in descending order, thereby forming the required bitonic sequence.
Working of Approach:
- Negate all the elements present at even indices so that they appear before the odd-indexed elements after sorting.
- Sort the entire array in ascending order, which automatically groups the negated and non-negated elements.
- Restore the original values of the first half by negating them again.
- Reverse the first half and second half of the array separately to obtain ascending and descending orders, respectively.
- Return the resulting array, which forms the required bitonic sequence.
Let us understand with an example:
Input: arr[] = [3, 1, 2, 4, 5, 9, 13, 14, 12]
- Array after multiplying by -1 to even placed elements: arr[] = [-3, 1, -2, 4, -5, 9, -13, 14, -12]
- Array after sorting: arr[] = [-13, -12, -5, -3, -2, 1, 4, 9, 14]
- Array after reverting negative values: arr[] = [13, 12, 5, 3, 2, 1, 4, 9, 14]
- After reversing the first half of array: arr[] = [2, 3, 5, 12, 13, 1, 4, 9, 14]
- After reversing the second half of array: arr[] = [2, 3, 5, 12, 13, 14, 9, 4, 1]
#include <iostream>
#include <vector>
using namespace std;
vector<int> bitonicGenerator(vector<int> &arr)
{
// Make all even indexed
// elements negative.
for (int i = 0; i < arr.size(); i++)
{
if (i % 2 == 0)
arr[i] = -arr[i];
}
// Sort the whole array.
sort(arr.begin(), arr.end());
// Find the middle index
// of the array.
int mid = (arr.size() - 1) / 2;
// Restore the original sign
// of the first half.
for (int i = 0; i <= mid; i++)
{
arr[i] = -arr[i];
}
// Reverse the first half
// of the array.
reverse(arr.begin(), arr.begin() + mid + 1);
// Reverse the second half
// of the array.
reverse(arr.begin() + mid + 1, arr.end());
return arr;
}
int main()
{
vector<int> arr = {3, 1, 2, 4, 5, 9, 13, 14, 12};
vector<int> res = bitonicGenerator(arr);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i != res.size() - 1)
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.*;
class GFG {
static ArrayList<Integer> bitonicGenerator(int[] arr)
{
// Make all even indexed
// elements negative.
for (int i = 0; i < arr.length; i++) {
if (i % 2 == 0)
arr[i] = -arr[i];
}
// Sort the whole array.
Arrays.sort(arr);
// Find the middle index
// of the array.
int mid = (arr.length - 1) / 2;
// Restore the original sign
// of the first half.
for (int i = 0; i <= mid; i++) {
arr[i] = -arr[i];
}
// Reverse the first half
// of the array.
int left = 0, right = mid;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
// Reverse the second half
// of the array.
left = mid + 1;
right = arr.length - 1;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
ArrayList<Integer> res = new ArrayList<>();
for (int x : arr)
res.add(x);
return res;
}
public static void main(String[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
ArrayList<Integer> res = bitonicGenerator(arr);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i != res.size() - 1)
System.out.print(", ");
}
System.out.println("]");
}
}
from typing import List
def bitonicGenerator(arr: List[int]) -> List[int]:
# Make all even indexed
# elements negative.
for i in range(len(arr)):
if i % 2 == 0:
arr[i] = -arr[i]
# Sort the whole array.
arr.sort()
# Find the middle index
# of the array.
mid = (len(arr) - 1) // 2
# Restore the original sign
# of the first half.
for i in range(mid + 1):
arr[i] = -arr[i]
# Reverse the first half
# of the array.
arr[:mid + 1] = arr[:mid + 1][::-1]
# Reverse the second half
# of the array.
arr[mid + 1:] = arr[mid + 1:][::-1]
return arr
if __name__ == '__main__':
arr = [3, 1, 2, 4, 5, 9, 13, 14, 12]
res = bitonicGenerator(arr)
print('[', end='')
for i in range(len(res)):
print(res[i], end='')
if i != len(res) - 1:
print(', ', end='')
print(']')
using System;
using System.Collections.Generic;
class GFG {
static List<int> bitonicGenerator(int[] arr)
{
// Make all even indexed
// elements negative.
for (int i = 0; i < arr.Length; i++) {
if (i % 2 == 0)
arr[i] = -arr[i];
}
// Sort the whole array.
Array.Sort(arr);
// Find the middle index
// of the array.
int mid = (arr.Length - 1) / 2;
// Restore the original sign
// of the first half.
for (int i = 0; i <= mid; i++) {
arr[i] = -arr[i];
}
// Reverse the first half
// of the array.
Array.Reverse(arr, 0, mid + 1);
// Reverse the second half
// of the array.
Array.Reverse(arr, mid + 1, arr.Length - mid - 1);
List<int> res = new List<int>();
foreach(int x in arr) res.Add(x);
return res;
}
static void Main(string[] args)
{
int[] arr = { 3, 1, 2, 4, 5, 9, 13, 14, 12 };
List<int> res = bitonicGenerator(arr);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i != res.Count - 1)
Console.Write(", ");
}
Console.WriteLine("]");
}
}
function bitonicGenerator(arr)
{
// Make all even indexed
// elements negative.
for (let i = 0; i < arr.length; i++) {
if (i % 2 === 0) {
arr[i] = -arr[i];
}
}
// Sort the whole array.
arr.sort((a, b) => a - b);
// Find the middle index
// of the array.
let mid = Math.floor((arr.length - 1) / 2);
// Restore the original sign
// of the first half.
for (let i = 0; i <= mid; i++) {
arr[i] = -arr[i];
}
// Reverse the first half
// of the array.
arr = arr.slice(0, mid + 1)
.reverse()
.concat(arr.slice(mid + 1));
// Reverse the second half
// of the array.
arr = arr.slice(0, mid + 1)
.concat(arr.slice(mid + 1).reverse());
return arr;
}
// Driver Code
let arr = [ 3, 1, 2, 4, 5, 9, 13, 14, 12 ];
let res = bitonicGenerator(arr);
console.log("[" + res.join(", ") + "]");
Output
[2, 3, 5, 12, 13, 14, 9, 4, 1]
Note: This method is only applicable if all the elements in the array are non-negative.