📜  煎饼分类问题

📅  最后修改于: 2021-05-04 12:28:28             🧑  作者: Mango

我们在上一篇文章中讨论了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