📜  使用O(1)额外空间合并和O(n lg n)时间进行合并排序

📅  最后修改于: 2021-04-27 19:43:13             🧑  作者: Mango

我们已经讨论了合并排序。如何修改算法以使合并在O(1)的额外空间中起作用,并且算法仍在O(n Log n)时间内起作用。我们可以假设输入值仅是整数。

例子:

Input : 5 4 3 2 1
Output : 1 2 3 4 5

Input : 999 612 589 856 56 945 243
Output : 56 243 589 612 856 945 999

对于整数类型,可以使用模数和除法的一些数学技巧就地进行合并排序。这意味着将两个元素值存储在一个索引上,并且可以使用模数和除法来提取。

首先,我们必须找到一个大于数组所有元素的值。现在我们可以将原始值存储为模数,将第二个值存储为除法。假设我们想将arr [i]arr [j]都存储在索引i(均指arr [i])中。首先,我们必须找到一个大于arr [i]和arr [j]的‘maxval’ 。现在我们可以存储为arr [i] = arr [i] + arr [j] * maxval 。现在arr [i]%maxval将给出arr [i]的原始值,而arr [i] / maxval将给出arr [j]的值。因此,以下是合并排序的实现。

C++
// C++ program to sort an array using merge sort such
// that merge operation takes O(1) extra space.
#include 
using namespace std;
void merge(int arr[], int beg, int mid, int end, int maxele)
{
    int i = beg;
    int j = mid + 1;
    int k = beg;
    while (i <= mid && j <= end) {
        if (arr[i] % maxele <= arr[j] % maxele) {
            arr[k] = arr[k] + (arr[i] % maxele) * maxele;
            k++;
            i++;
        }
        else {
            arr[k] = arr[k] + (arr[j] % maxele) * maxele;
            k++;
            j++;
        }
    }
    while (i <= mid) {
        arr[k] = arr[k] + (arr[i] % maxele) * maxele;
        k++;
        i++;
    }
    while (j <= end) {
        arr[k] = arr[k] + (arr[j] % maxele) * maxele;
        k++;
        j++;
    }
 
    // Obtaining actual values
    for (int i = beg; i <= end; i++)
        arr[i] = arr[i] / maxele;
}
 
// Recursive merge sort with extra parameter, naxele
void mergeSortRec(int arr[], int beg, int end, int maxele)
{
    if (beg < end) {
        int mid = (beg + end) / 2;
        mergeSortRec(arr, beg, mid, maxele);
        mergeSortRec(arr, mid + 1, end, maxele);
        merge(arr, beg, mid, end, maxele);
    }
}
 
// This functions finds max element and calls recursive
// merge sort.
void mergeSort(int arr[], int n)
{
   int maxele = *max_element(arr, arr+n) + 1;
   mergeSortRec(arr, 0, n-1, maxele);
}
 
int main()
{
    int arr[] = { 999, 612, 589, 856, 56, 945, 243 };
    int n = sizeof(arr) / sizeof(arr[0]);
     
    mergeSort(arr, n);
 
    cout << "Sorted array \n";
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
    return 0;
}


Java
// Java program to sort an array
// using merge sort such that
// merge operation takes O(1)
// extra space.
import java.util.Arrays;
 
class GFG
{
 
    static void merge(int[] arr, int beg,
                        int mid, int end,
                        int maxele)
    {
        int i = beg;
        int j = mid + 1;
        int k = beg;
        while (i <= mid && j <= end)
        {
            if (arr[i] % maxele <=
                arr[j] % maxele)
            {
                arr[k] = arr[k] + (arr[i]
                        % maxele) * maxele;
                k++;
                i++;
            }
            else
            {
                arr[k] = arr[k] +
                        (arr[j] % maxele)
                        * maxele;
                k++;
                j++;
            }
        }
        while (i <= mid)
        {
            arr[k] = arr[k] + (arr[i]
                    % maxele) * maxele;
            k++;
            i++;
        }
        while (j <= end)
        {
            arr[k] = arr[k] + (arr[j]
                    % maxele) * maxele;
            k++;
            j++;
        }
 
        // Obtaining actual values
        for (i = beg; i <= end; i++)
        {
            arr[i] = arr[i] / maxele;
        }
    }
 
    // Recursive merge sort
    // with extra parameter, naxele
    static void mergeSortRec(int[] arr, int beg,
            int end, int maxele)
    {
        if (beg < end)
        {
            int mid = (beg + end) / 2;
            mergeSortRec(arr, beg,
                        mid, maxele);
            mergeSortRec(arr, mid + 1,
                        end, maxele);
            merge(arr, beg, mid,
                    end, maxele);
        }
    }
 
    // This functions finds
    // max element and calls
    // recursive merge sort.
    static void mergeSort(int[] arr, int n)
    {
        int maxele = Arrays.stream(arr).max().getAsInt() + 1;
        mergeSortRec(arr, 0, n - 1, maxele);
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        int[] arr = {999, 612, 589,
                    856, 56, 945, 243};
        int n = arr.length;
 
        mergeSort(arr, n);
 
        System.out.println("Sorted array ");
        for (int i = 0; i < n; i++)
        {
            System.out.print(arr[i] + " ");
        }
    }
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 program to sort an array using
# merge sort such that merge operation
# takes O(1) extra space.
def merge(arr, beg, mid, end, maxele):
     
    i = beg
    j = mid + 1
    k = beg
     
    while (i <= mid and j <= end):
        if (arr[i] % maxele <= arr[j] % maxele):
            arr[k] = arr[k] + (arr[i] %
                    maxele) * maxele
            k += 1
            i += 1
        else:
            arr[k] = arr[k] + (arr[j] %
                    maxele) * maxele
            k += 1
            j += 1
             
    while (i <= mid):
        arr[k] = arr[k] + (arr[i] %
                maxele) * maxele
        k += 1
        i += 1
    while (j <= end):
        arr[k] = arr[k] + (arr[j] %
                maxele) * maxele
        k += 1
        j += 1
 
    # Obtaining actual values
    for i in range(beg, end + 1):
        arr[i] = arr[i] // maxele
 
# Recursive merge sort with extra
# parameter, naxele
def mergeSortRec(arr, beg, end, maxele):
     
    if (beg < end):
        mid = (beg + end) // 2
        mergeSortRec(arr, beg, mid, maxele)
        mergeSortRec(arr, mid + 1, end, maxele)
        merge(arr, beg, mid, end, maxele)
 
# This functions finds max element and
# calls recursive merge sort.
def mergeSort(arr, n):
     
   maxele = max(arr) + 1
   mergeSortRec(arr, 0, n - 1, maxele)
 
# Driver Code
if __name__ == '__main__':
 
    arr = [ 999, 612, 589, 856, 56, 945, 243 ]
    n =  len(arr)
    mergeSort(arr, n)
 
    print("Sorted array")
     
    for i in range(n):
        print(arr[i], end = " ")
 
# This code is contributed by mohit kumar 29


C#
// C# program to sort an array
// using merge sort such that
// merge operation takes O(1)
// extra space.
using System;
using System.Linq;
 
class GFG
{
static void merge(int []arr, int beg,
                  int mid, int end,
                  int maxele)
{
    int i = beg;
    int j = mid + 1;
    int k = beg;
    while (i <= mid && j <= end)
    {
        if (arr[i] %
            maxele <= arr[j] % maxele)
        {
            arr[k] = arr[k] + (arr[i] %
                     maxele) * maxele;
            k++;
            i++;
        }
        else
        {
            arr[k] = arr[k] +
                    (arr[j] % maxele) *
                              maxele;
            k++;
            j++;
        }
    }
    while (i <= mid)
    {
        arr[k] = arr[k] + (arr[i] %
                 maxele) * maxele;
        k++;
        i++;
    }
    while (j <= end)
    {
        arr[k] = arr[k] + (arr[j] %
                 maxele) * maxele;
        k++;
        j++;
    }
 
    // Obtaining actual values
    for ( i = beg; i <= end; i++)
        arr[i] = arr[i] / maxele;
}
 
// Recursive merge sort
// with extra parameter, naxele
static void mergeSortRec(int []arr, int beg,
                         int end, int maxele)
{
    if (beg < end)
    {
        int mid = (beg + end) / 2;
        mergeSortRec(arr, beg,
                     mid, maxele);
        mergeSortRec(arr, mid + 1,
                     end, maxele);
        merge(arr, beg, mid,
              end, maxele);
    }
}
 
// This functions finds
// max element and calls
// recursive merge sort.
static void mergeSort(int []arr, int n)
{
    int maxele = arr.Max() + 1;
    mergeSortRec(arr, 0, n - 1, maxele);
}
 
//Driver code
public static void Main ()
{
    int []arr = {999, 612, 589,
                 856, 56, 945, 243};
    int n = arr.Length;
 
    mergeSort(arr, n);
 
    Console.WriteLine("Sorted array ");
    for (int i = 0; i < n; i++)
        Console.Write( arr[i] + " ");
}
}
 
// This code is contributed
// by inder_verma.


输出:
Sorted array 
56 243 589 612 856 945 999