We have discussed Pancake Sorting in the previous post. Following is a problem based on Pancake Sorting.
Given an unsorted array, sort the given array. You are allowed to do only following operation on array.
flip(arr, i): Reverse array from 0 to i
Imagine a hypothetical machine where flip(i) always takes O(1) time. Write an efficient program for sorting a given array in O(nLogn) time on the given machine. If we apply the same algorithm here, the time taken will be O(n^2) because the algorithm calls findMax() in a loop and find findMax() takes O(n) time even on this hypothetical machine.
We can use insertion sort that uses binary search. The idea is to run a loop from second element to last element (from i = 1 to n-1), and one by one insert arr[i] in arr[0..i-1] (like standard insertion sort algorithm). When we insert an element arr[i], we can use binary search to find position of arr[i] in O(Logi) time. Once we have the position, we can use some flip operations to put arr[i] at its new place. Following are abstract steps.
// Standard Insertion Sort Loop that starts from second element
for (i=1; i O(n)
{
int key = arr[i];
// Find index of ceiling of arr[i] in arr[0..i-1] using binary search
j = celiSearch(arr, key, 0, i-1); ----> O(logn) (See this)
// Apply some flip operations to put arr[i] at correct place
}
Since flip operation takes O(1) on given hypothetical machine, total running time of above algorithm is O(nlogn). Thanks to Kumar for suggesting above problem and algorithm.
Let us see how does the above algorithm work. ceilSearch() actually returns the index of the smallest element which is greater than arr[i] in arr[0..i-1]. If there is no such element, it returns -1. Let the returned value be j. If j is -1, then we don’t need to do anything as arr[i] is already the greatest element among arr[0..i]. Otherwise we need to put arr[i] just before arr[j].
So how to apply flip operations to put arr[i] just before arr[j] using values of i and j. Let us take an example to understand this. Let i be 6 and current array be {12, 15, 18, 30, 35, 40, 20, 6, 90, 80}. To put 20 at its new place, the array should be changed to {12, 15, 18, 20, 30, 35, 40, 6, 90, 80}. We apply following steps to put 20 at its new place.
1) Find j using ceilSearch (In the above example j is 3).
2) flip(arr, j-1) (array becomes {18, 15, 12, 30, 35, 40, 20, 6, 90, 80})
3) flip(arr, i-1); (array becomes {40, 35, 30, 12, 15, 18, 20, 6, 90, 80})
4) flip(arr, i); (array becomes {20, 18, 15, 12, 30, 35, 40, 6, 90, 80})
5) flip(arr, j); (array becomes {12, 15, 18, 20, 30, 35, 40, 6, 90, 80})
Following is the implementation of the above algorithm.
C++
#include<bits/stdc++.h>
using namespace std;
int ceilSearch( int arr[], int low, int high, int x)
{
int mid;
if (x <= arr[low])
return low;
if (x > arr[high])
return -1;
mid = (low + high)/2;
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
{
if (mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
void flip( int arr[], int i)
{
int temp, start = 0;
while (start < i)
{
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i--;
}
}
void insertionSort( int arr[], int size)
{
int i, j;
for (i = 1; i < size; i++)
{
int j = ceilSearch(arr, 0, i-1, arr[i]);
if (j != -1)
{
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
void printArray( int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
cout<<arr[i]<< " " ;
}
int main()
{
int arr[] = {18, 40, 35, 12, 30, 35, 20, 6, 90, 80};
int n = sizeof (arr)/ sizeof (arr[0]);
insertionSort(arr, n);
printArray(arr, n);
return 0;
}
|
C
#include <stdlib.h>
#include <stdio.h>
int ceilSearch( int arr[], int low, int high, int x)
{
int mid;
if (x <= arr[low])
return low;
if (x > arr[high])
return -1;
mid = (low + high)/2;
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
{
if (mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
void flip( int arr[], int i)
{
int temp, start = 0;
while (start < i)
{
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i--;
}
}
void insertionSort( int arr[], int size)
{
int i, j;
for (i = 1; i < size; i++)
{
int j = ceilSearch(arr, 0, i-1, arr[i]);
if (j != -1)
{
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
void printArray( int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
printf ( "%d " , arr[i]);
}
int main()
{
int arr[] = {18, 40, 35, 12, 30, 35, 20, 6, 90, 80};
int n = sizeof (arr)/ sizeof (arr[0]);
insertionSort(arr, n);
printArray(arr, n);
return 0;
}
|
Java
import java.io.*;
public class GfG {
static int ceilSearch( int arr[], int low, int high, int x)
{
int mid;
if (x <= arr[low])
return low;
if (x > arr[high])
return - 1 ;
mid = (low + high)/ 2 ;
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
{
if (mid + 1 <= high && x <= arr[mid+ 1 ])
return mid + 1 ;
else
return ceilSearch(arr, mid+ 1 , high, x);
}
if (mid - 1 >= low && x > arr[mid- 1 ])
return mid;
else
return ceilSearch(arr, low, mid - 1 , x);
}
static void flip( int arr[], int i)
{
int temp, start = 0 ;
while (start < i)
{
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i--;
}
}
static void insertionSort( int arr[], int size)
{
int i;
for (i = 1 ; i < size; i++)
{
int j = ceilSearch(arr, 0 , i- 1 , arr[i]);
if (j != - 1 )
{
flip(arr, j- 1 );
flip(arr, i- 1 );
flip(arr, i);
flip(arr, j);
}
}
}
static void printArray( int arr[], int n)
{
int i;
for (i = 0 ; i < n; ++i)
System.out.print(arr[i] + " " );
}
public static void main(String[] args)
{
int arr[] = { 18 , 40 , 35 , 12 , 30 , 35 , 20 , 6 , 90 , 80 };
int n = arr.length;
insertionSort(arr, n);
printArray(arr, n);
}
}
|
Python3
def ceilSearch(arr,low,high,x):
if x < = arr[low]:
return low
if x > arr[high]:
return - 1
mid = (low + high) / / 2
if (arr[mid] = = x):
return mid
if (arr[mid] < x):
if (mid + 1 < = high and x < = arr[mid + 1 ]):
return mid + 1
else :
return ceilSearch(arr, mid + 1 , high, x)
if (mid - 1 > = low and x > arr[mid - 1 ]):
return mid
else :
return ceilSearch(arr, low, mid - 1 , x)
def flip(arr,i):
start = 0 ;
while (start < i):
temp = arr[start]
arr[start] = arr[i]
arr[i] = temp
start + = 1
i - = 1
def insertionSort(arr):
for i in range ( 1 , len (arr)):
j = ceilSearch(arr, 0 , i - 1 , arr[i])
if (j ! = - 1 ):
flip(arr, j - 1 )
flip(arr, i - 1 )
flip(arr, i)
flip(arr, j)
def printArray(arr):
for i in range ( 0 , len (arr)):
print (arr[i],end = " " )
arr = [ 18 , 40 , 35 , 12 , 30 , 35 , 20 , 6 , 90 , 80 ]
insertionSort(arr)
printArray(arr)
|
C#
using System;
class GFG
{
static int ceilSearch( int []arr, int low,
int high, int x)
{
int mid;
if (x <= arr[low])
return low;
if (x > arr[high])
return -1;
mid = (low + high) / 2;
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
{
if (mid + 1 <= high && x <= arr[mid + 1])
return mid + 1;
else
return ceilSearch(arr, mid + 1, high, x);
}
if (mid - 1 >= low && x > arr[mid - 1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
static void flip( int []arr, int i)
{
int temp, start = 0;
while (start < i)
{
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i--;
}
}
static void insertionSort( int []arr, int size)
{
int i;
for (i = 1; i < size; i++)
{
int j = ceilSearch(arr, 0, i - 1, arr[i]);
if (j != -1)
{
flip(arr, j - 1);
flip(arr, i - 1);
flip(arr, i);
flip(arr, j);
}
}
}
static void printArray( int []arr, int n)
{
int i;
for (i = 0; i < n; ++i)
Console.Write(arr[i] + " " );
}
public static void Main(String[] args)
{
int []arr = {18, 40, 35, 12, 30,
35, 20, 6, 90, 80};
int n = arr.Length;
insertionSort(arr, n);
printArray(arr, n);
}
}
|
Javascript
<script>
function ceilSearch(arr, low, high, x)
{
var mid;
if (x <= arr[low])
return low;
if (x > arr[high])
return -1;
mid = parseInt((low + high)/2);
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
{
if (mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
function flip( arr, i)
{
var temp, start = 0;
while (start < i)
{
temp = arr[start];
arr[start] = arr[i];
arr[i] = temp;
start++;
i--;
}
}
function insertionSort( arr, size)
{
var i, j;
for (i = 1; i < size; i++)
{
var j = ceilSearch(arr, 0, i-1, arr[i]);
if (j != -1)
{
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
function printArray(arr, n)
{
var i;
for (i = 0; i < n; ++i)
document.write(arr[i]+ " " );
}
var arr = [18, 40, 35, 12, 30, 35, 20, 6, 90, 80];
var n = arr.length;
insertionSort(arr, n);
printArray(arr, n);
</script>
|
Output6 12 18 20 30 35 35 40 80 90
Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.
Time Complexity: O(n log n)
Auxiliary space: O(log n)