我们在上一篇文章中讨论了Pancake Sorting。以下是基于煎饼分类的问题。
给定一个未排序的数组,对给定的数组进行排序。只允许对数组执行以下操作。
flip(arr, i): Reverse array from 0 to i
想象一个假设的机器,其中flip(i)总是需要O(1)时间。编写一个有效的程序,以在给定机器上以O(nLogn)时间对给定数组进行排序。如果在此处应用相同的算法,则所需时间将为O(n ^ 2),因为该算法在循环中调用findMax(),即使在此假设的机器上,findfindMax()也会花费O(n)的时间。
我们可以使用使用二进制搜索的插入排序。这个想法是运行从第二个元素到最后一个元素的循环(从i = 1到n-1),并在arr [0..i-1]中一个接一个地插入arr [i](类似于标准插入排序算法) 。当我们插入一个元素arr [i]时,我们可以使用二进制搜索来找到arr [i]在O(Logi)时间中的位置。一旦有了位置,我们就可以使用一些翻转操作将arr [i]放到新位置。以下是抽象步骤。
// 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
}
由于翻转操作在给定的假设机器上需要O(1),因此上述算法的总运行时间为O(nlogn)。感谢Kumar建议上述问题和算法。
让我们看看上面的算法是如何工作的。 ceilSearch()实际上返回大于arr [0..i-1]中的arr [i]的最小元素的索引。如果没有这样的元素,则返回-1。令返回值为j。如果j为-1,那么我们不需要做任何事情,因为arr [i]已经是arr [0..i]中最大的元素。否则,我们需要将arr [i]放在arr [j]之前。
因此,如何使用i和j的值应用翻转操作将arr [i]放在arr [j]之前。让我们以一个例子来理解这一点。令i是6和当前数组是{12,15,18,30,35,40,20,6,90,80}。把20在其新的位置,阵列应改为{12,15,18,20,30,35,40,6,90,80}。我们采用以下步骤将20放置在新位置。
1)使用ceilSearch查找j(在上面的示例中j为3)。
2)翻转(ARR,J-1)(阵列为{18,15,12,30,35,40,20,6,90,80})
3)flip(arr,i-1); (阵列为{40,35,30,12,15,18,20,6,90,80})
4)翻转(arr,i); (阵列为{20,18,15,12,30,35,40,6,90,80})
5)flip(arr,j); (阵列为{12,15,18,20,30,35,40,6,90,80})
以下是上述算法的实现。
C++
// C++ program of Pancake Sorting Problem
#include
using namespace std;
/* A Binary Search based function to
get index of ceiling of x in
arr[low..high] */
int ceilSearch(int arr[], int low, int high, int x)
{
int mid;
/* If x is smaller than or equal
to the first element,
then return the first element */
if(x <= arr[low])
return low;
/* If x is greater than the
last element, then return -1 */
if(x > arr[high])
return -1;
/* get the index of middle
element of arr[low..high]*/
mid = (low + high)/2; /* low + (high – low)/2 */
/* If x is same as middle
element, then return mid */
if(arr[mid] == x)
return mid;
/* If x is greater than arr[mid],
then either arr[mid + 1]
is ceiling of x, or ceiling
lies in arr[mid+1...high] */
if(arr[mid] < x)
{
if(mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
/* If x is smaller than arr[mid], then either arr[mid]
is ceiling of x or ceiling lies in arr[mid-1...high] */
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
/* Reverses arr[0..i] */
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--;
}
}
/* Function to sort an array using
insertion sort, binary search and flip */
void insertionSort(int arr[], int size)
{
int i, j;
// Start from the second element
// and one by one insert arr[i]
// in already sorted arr[0..i-1]
for(i = 1; i < size; i++)
{
// Find the smallest element in arr[0..i-1]
// which is also greater than
// or equal to arr[i]
int j = ceilSearch(arr, 0, i-1, arr[i]);
// Check if there was no element
// greater than arr[i]
if (j != -1)
{
// Put arr[i] before arr[j] using
// following four flip operations
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
/* A utility function to print an array of size n */
void printArray(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
cout<
C
// C program of Pancake Sorting Problem
#include
#include
/* A Binary Search based function to get index of ceiling of x in
arr[low..high] */
int ceilSearch(int arr[], int low, int high, int x)
{
int mid;
/* If x is smaller than or equal to the first element,
then return the first element */
if(x <= arr[low])
return low;
/* If x is greater than the last element, then return -1 */
if(x > arr[high])
return -1;
/* get the index of middle element of arr[low..high]*/
mid = (low + high)/2; /* low + (high – low)/2 */
/* If x is same as middle element, then return mid */
if(arr[mid] == x)
return mid;
/* If x is greater than arr[mid], then either arr[mid + 1]
is ceiling of x, or ceiling lies in arr[mid+1...high] */
if(arr[mid] < x)
{
if(mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
/* If x is smaller than arr[mid], then either arr[mid]
is ceiling of x or ceiling lies in arr[mid-1...high] */
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
/* Reverses arr[0..i] */
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--;
}
}
/* Function to sort an array using insertion sort, binary search and flip */
void insertionSort(int arr[], int size)
{
int i, j;
// Start from the second element and one by one insert arr[i]
// in already sorted arr[0..i-1]
for(i = 1; i < size; i++)
{
// Find the smallest element in arr[0..i-1] which is also greater than
// or equal to arr[i]
int j = ceilSearch(arr, 0, i-1, arr[i]);
// Check if there was no element greater than arr[i]
if (j != -1)
{
// Put arr[i] before arr[j] using following four flip operations
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
/* A utility function to print an array of size n */
void printArray(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
printf("%d ", arr[i]);
}
/* Driver program to test insertion sort */
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
// Java program of Pancake Sorting Problem
class GfG {
/* A Binary Search based function to get index of ceiling of x in
arr[low..high] */
static int ceilSearch(int arr[], int low, int high, int x)
{
int mid;
/* If x is smaller than or equal to the first element,
then return the first element */
if(x <= arr[low])
return low;
/* If x is greater than the last element, then return -1 */
if(x > arr[high])
return -1;
/* get the index of middle element of arr[low..high]*/
// low + (high - low)/2
mid = (low + high)/2;
/* If x is same as middle element, then return mid */
if(arr[mid] == x)
return mid;
/* If x is greater than arr[mid], then either arr[mid + 1]
is ceiling of x, or ceiling lies in arr[mid+1...high] */
if(arr[mid] < x)
{
if(mid + 1 <= high && x <= arr[mid+1])
return mid + 1;
else
return ceilSearch(arr, mid+1, high, x);
}
/* If x is smaller than arr[mid], then either arr[mid]
is ceiling of x or ceiling lies in arr[mid-1...high] */
if (mid - 1 >= low && x > arr[mid-1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
/* Reverses arr[0..i] */
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--;
}
}
/* Function to sort an array using insertion sort, binary search and flip */
static void insertionSort(int arr[], int size)
{
int i;
// Start from the second element and one by one insert arr[i]
// in already sorted arr[0..i-1]
for(i = 1; i < size; i++)
{
// Find the smallest element in arr[0..i-1] which is also greater than
// or equal to arr[i]
int j = ceilSearch(arr, 0, i-1, arr[i]);
// Check if there was no element greater than arr[i]
if (j != -1)
{
// Put arr[i] before arr[j] using following four flip operations
flip(arr, j-1);
flip(arr, i-1);
flip(arr, i);
flip(arr, j);
}
}
}
/* A utility function to print an array of size n */
static void printArray(int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
System.out.print(arr[i] + " ");
}
/* Driver program to test insertion sort */
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);
}
}
Python
# Python program of Pancake Sorting Problem
#A Binary Search based function to get index of ceiling of x in arr[low..high]
def ceilSearch(arr,low,high,x):
#If x is smaller than or equal to the first element,
#then return the first element
if x <= arr[low]:
return low
#If x is greater than the last element, then return -1
if x > arr[high]:
return -1
#get the index of middle element of arr[low..high]
mid = (low + high)/2 #low + (high-low)/2
#If x is same as middle element, then return mid
if(arr[mid] == x):
return mid
#If x is greater than arr[mid], then either arr[mid + 1]
#is ceiling of x, or ceiling lies in arr[mid+1...high]
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 x is smaller than arr[mid], then either arr[mid]
#is ceiling of x or ceiling lies in arr[mid-1...high]
if (mid - 1 >= low and x > arr[mid-1]):
return mid
else:
return ceilSearch(arr, low, mid - 1, x)
#Reverses arr[0..i] */
def flip(arr,i):
start = 0;
while (start < i):
temp = arr[start]
arr[start] = arr[i]
arr[i] = temp
start+=1
i-=1
#Function to sort an array using insertion sort, binary search and flip
def insertionSort(arr):
#Start from the second element and one by one insert arr[i]
#in already sorted arr[0..i-1]
for i in range(1,len(arr)):
#Find the smallest element in arr[0..i-1] which is also greater than
#or equal to arr[i]
j = ceilSearch(arr, 0, i-1, arr[i])
#Check if there was no element greater than arr[i]
if (j != -1):
#Put arr[i] before arr[j] using following four flip operations
flip(arr, j-1)
flip(arr, i-1)
flip(arr, i)
flip(arr, j)
# A utility function to print an array of size n
def printArray(arr):
for i in range(0,len(arr)):
print arr[i],
#Driver function to test above function
arr=[18, 40, 35, 12, 30, 35, 20, 6, 90, 80]
insertionSort(arr)
printArray(arr)
#This code is contributed by Devesh Agrawal
C#
// C# program of Pancake Sorting Problem
using System;
class GFG
{
// A Binary Search based function to get
// index of ceiling of x in arr[low..high]
static int ceilSearch(int []arr, int low,
int high, int x)
{
int mid;
// If x is smaller than or equal to
// the first element,
// then return the first element
if(x <= arr[low])
return low;
// If x is greater than the last element,
// then return -1
if(x > arr[high])
return -1;
// get the index of middle element
// of arr[low..high]
// low + (high - low)/2
mid = (low + high) / 2;
// If x is same as middle element,
// then return mid
if(arr[mid] == x)
return mid;
// If x is greater than arr[mid],
// then either arr[mid + 1] is ceiling of x,
// or ceiling lies in arr[mid+1...high]
if(arr[mid] < x)
{
if(mid + 1 <= high && x <= arr[mid + 1])
return mid + 1;
else
return ceilSearch(arr, mid + 1, high, x);
}
// If x is smaller than arr[mid],
// then either arr[mid] is ceiling of x
// or ceiling lies in arr[mid-1...high]
if (mid - 1 >= low && x > arr[mid - 1])
return mid;
else
return ceilSearch(arr, low, mid - 1, x);
}
// Reverses arr[0..i]
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--;
}
}
// Function to sort an array using insertion sort,
// binary search and flip
static void insertionSort(int []arr, int size)
{
int i;
// Start from the second element and
// one by one insert arr[i] in
// already sorted arr[0..i-1]
for(i = 1; i < size; i++)
{
// Find the smallest element in arr[0..i-1]
// which is also greater than or equal to arr[i]
int j = ceilSearch(arr, 0, i - 1, arr[i]);
// Check if there was no element greater than arr[i]
if (j != -1)
{
// Put arr[i] before arr[j] using
// following four flip operations
flip(arr, j - 1);
flip(arr, i - 1);
flip(arr, i);
flip(arr, j);
}
}
}
// A utility function to print an array of size n
static void printArray(int []arr, int n)
{
int i;
for (i = 0; i < n; ++i)
Console.Write(arr[i] + " ");
}
// Driver Code
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);
}
}
// This code is contributed by Princi Singh
输出:
6 12 18 20 30 35 35 40 80 90