📌  相关文章
📜  在线性时间内对n个数字进行排序,范围从0到n ^ 2 – 1

📅  最后修改于: 2021-04-29 07:54:47             🧑  作者: Mango

给定一个大小为n的数字数组。还假定数组元素的范围是0到n 2 –1。以线性时间对给定数组进行排序。

例子:

Since there are 5 elements, the elements can be from 0 to 24.
Input: arr[] = {0, 23, 14, 12, 9}
Output: arr[] = {0, 9, 12, 14, 23}

Since there are 3 elements, the elements can be from 0 to 8.
Input: arr[] = {7, 0, 2}
Output: arr[] = {0, 2, 7}

解决方案:如果使用计数排序,由于给定范围的大小为n ^ 2,因此将花费O(n ^ 2)时间。使用任何基于比较的排序(例如合并排序,堆排序等)将花费O(nLogn)时间。
现在出现问题了,如何在0(n)中执行此操作?首先,有可能吗?我们可以使用有问题的数据吗? n个数字,范围从0到n 2 – 1?

这个想法是使用基数排序。以下是标准的Radix Sort算法。

1) Do following for each digit i where i varies from least 
   significant digit to the most significant digit.
…………..a) Sort input array using counting sort (or any stable 
         sort) according to the i’th digit

设输入整数为d位。基数排序需要O(d *(n + b))时间,其中b是表示数字的基数,例如对于十进制,b是10。由于n 2 -1是最大可能值,所以d的值将是是O(log b (n))。因此,总体时间复杂度为O((n + b)* O(log b (n))。它看起来比基于比较的排序算法对大k的时间复杂度高。想法是更改基数b。 b作为n,O(log b (n))的值变为O(1),总时间复杂度变为O(n)。

arr[] = {0, 10, 13, 12, 7}

Let us consider the elements in base 5. For example 13 in
base 5 is 23, and 7 in base 5 is 12.
arr[] = {00(0), 20(10), 23(13), 22(12), 12(7)}

After first iteration (Sorting according to the last digit in 
base 5),  we get.
arr[] = {00(0), 20(10), 12(7), 22(12), 23(13)}

After second iteration, we get
arr[] = {00(0), 12(7), 20(10), 22(12), 23(13)}

以下是对大小为n的数组进行排序的实现,其中元素的范围为0到n 2 – 1。

C++
#include
using namespace std;
 
// A function to do counting sort of arr[] according to
// the digit represented by exp.
int countSort(int arr[], int n, int exp)
{
 
    int output[n]; // output array
    int i, count[n] ;
    for (int i=0; i < n; i++)
       count[i] = 0;
 
    // Store count of occurrences in count[]
    for (i = 0; i < n; i++)
        count[ (arr[i]/exp)%n ]++;
 
    // Change count[i] so that count[i] now contains actual
    // position of this digit in output[]
    for (i = 1; i < n; i++)
        count[i] += count[i - 1];
 
    // Build the output array
    for (i = n - 1; i >= 0; i--)
    {
        output[count[ (arr[i]/exp)%n] - 1] = arr[i];
        count[(arr[i]/exp)%n]--;
    }
 
    // Copy the output array to arr[], so that arr[] now
    // contains sorted numbers according to current digit
    for (i = 0; i < n; i++)
        arr[i] = output[i];
}
 
 
// The main function to that sorts arr[] of size n using Radix Sort
void sort(int arr[], int n)
{
    // Do counting sort for first digit in base n. Note that
    // instead of passing digit number, exp (n^0 = 1) is passed.
    countSort(arr, n, 1);
 
    // Do counting sort for second digit in base n. Note that
    // instead of passing digit number, exp (n^1 = n) is passed.
    countSort(arr, n, n);
}
 
// A utility function to print an array
void printArr(int arr[], int n)
{
    for (int i = 0; i < n; i++)
        cout << arr[i] << " ";
}
 
// Driver program to test above functions
int main()
{
    // Since array size is 7, elements should be from 0 to 48
    int arr[] = {40, 12, 45, 32, 33, 1, 22};
    int n = sizeof(arr)/sizeof(arr[0]);
    cout << "Given array is n";
    printArr(arr, n);
 
    sort(arr, n);
 
    cout << "nSorted array is n";
    printArr(arr, n);
    return 0;
}


Java
// Java program to sort an array of size n where elements are
// in range from 0 to n^2 – 1.
class Sort1ToN2
{
    // A function to do counting sort of arr[] according to
    // the digit represented by exp.
    void countSort(int arr[], int n, int exp)
    {
        int output[] = new int[n]; // output array
        int i, count[] = new int[n] ;
        for (i=0; i < n; i++)
           count[i] = 0;
 
        // Store count of occurrences in count[]
        for (i = 0; i < n; i++)
            count[ (arr[i]/exp)%n ]++;
 
        // Change count[i] so that count[i] now contains actual
        // position of this digit in output[]
        for (i = 1; i < n; i++)
            count[i] += count[i - 1];
 
        // Build the output array
        for (i = n - 1; i >= 0; i--)
        {
            output[count[ (arr[i]/exp)%n] - 1] = arr[i];
            count[(arr[i]/exp)%n]--;
        }
 
        // Copy the output array to arr[], so that arr[] now
        // contains sorted numbers according to current digit
        for (i = 0; i < n; i++)
            arr[i] = output[i];
    }
 
 
    // The main function to that sorts arr[] of size n using Radix Sort
    void sort(int arr[], int n)
    {
        // Do counting sort for first digit in base n. Note that
        // instead of passing digit number, exp (n^0 = 1) is passed.
        countSort(arr, n, 1);
 
        // Do counting sort for second digit in base n. Note that
        // instead of passing digit number, exp (n^1 = n) is passed.
        countSort(arr, n, n);
    }
 
    // A utility function to print an array
    void printArr(int arr[], int n)
    {
        for (int i = 0; i < n; i++)
            System.out.print(arr[i]+" ");
    }
 
    // Driver program to test above functions
    public static void main(String args[])
    {
        Sort1ToN2 ob = new Sort1ToN2();
 
        // Since array size is 7, elements should be from 0 to 48
        int arr[] = {40, 12, 45, 32, 33, 1, 22};
        int n = arr.length;
        System.out.println("Given array");
        ob.printArr(arr, n);
 
        ob.sort(arr, n);
 
        System.out.println("Sorted array");
        ob.printArr(arr, n);
    }
}
/*This code is contributed by Rajat Mishra */


Python3
# Python3 the implementation to sort an
# array of size n
 
# A function to do counting sort of arr[]
# according to the digit represented by exp.
def countSort(arr, n, exp):
    output = [0] * n # output array
    count = [0] * n
    for i in range(n):
        count[i] = 0
 
    # Store count of occurrences in count[]
    for i in range(n):
        count[ (arr[i] // exp) % n ] += 1
 
    # Change count[i] so that count[i] now contains
    # actual position of this digit in output[]
    for i in range(1, n):
        count[i] += count[i - 1]
 
    # Build the output array
    for i in range(n - 1, -1, -1):
 
        output[count[ (arr[i] // exp) % n] - 1] = arr[i]
        count[(arr[i] // exp) % n] -= 1
 
    # Copy the output array to arr[], so that
    # arr[] now contains sorted numbers according
    # to current digit
    for i in range(n):
        arr[i] = output[i]
 
# The main function to that sorts arr[] of
# size n using Radix Sort
def sort(arr, n) :
     
    # Do counting sort for first digit in base n.
    # Note that instead of passing digit number,
    # exp (n^0 = 1) is passed.
    countSort(arr, n, 1)
 
    # Do counting sort for second digit in base n.
    # Note that instead of passing digit number,
    # exp (n^1 = n) is passed.
    countSort(arr, n, n)
 
# Driver Code
if __name__ =="__main__":
     
    # Since array size is 7, elements should
    # be from 0 to 48
    arr = [40, 12, 45, 32, 33, 1, 22]
    n = len(arr)
    print("Given array is")
    print(*arr)
     
    sort(arr, n)
     
    print("Sorted array is")
    print(*arr)
 
# This code is contribute by
# Shubham Singh(SHUBHAMSINGH10)


C#
// C# program to sort an array of
// size n where elements are
// in range from 0 to n^2 – 1.
using System;
 
class GFG {
     
    // A function to do counting
    // sort of arr[] according to
    // the digit represented by exp.
    static void countSort(int[] arr,
                          int n,
                          int exp)
    {
         
        // output array
        int[] output = new int[n];
        int[] count = new int[n] ;
        int i;
        for (i = 0; i < n; i++)
        count[i] = 0;
 
        // Store count of
        // occurrences in count[]
        for (i = 0; i < n; i++)
            count[(arr[i] / exp) % n ]++;
 
        // Change count[i] so that
        // count[i] now contains actual
        // position of this digit in output[]
        for (i = 1; i < n; i++)
            count[i] += count[i - 1];
 
        // Build the output array
        for (i = n - 1; i >= 0; i--)
        {
            output[count[(arr[i] /
                   exp) % n] - 1] = arr[i];
            count[(arr[i] / exp) % n]--;
        }
 
        // Copy the output array to
        // arr[], so that arr[] now
        // contains sorted numbers
        // according to current digit
        for (i = 0; i < n; i++)
            arr[i] = output[i];
    }
 
 
    // The main function to that
    // sorts arr[] of size n
    // using Radix Sort
    static void sort(int[] arr, int n)
    {
         
        // Do counting sort for first
        // digit in base n. Note that
        // instead of passing digit number,
        // exp (n^0 = 1) is passed.
        countSort(arr, n, 1);
 
        // Do counting sort for second
        // digit in base n. Note that
        // instead of passing digit number,
        // exp (n^1 = n) is passed.
        countSort(arr, n, n);
    }
 
    // A utility function
    // to print an array
    static void printArr(int[] arr, int n)
    {
        for (int i = 0; i < n; i++)
            Console.Write(arr[i] + " ");
    }
 
    // Driver Code
    static public void Main ()
    {
         
        // Since array size is 7,
        // elements should be
        // from 0 to 48
        int[] arr = {40, 12, 45, 32, 33, 1, 22};
        int n = arr.Length;
        Console.WriteLine("Given array");
        printArr(arr, n);
 
        sort(arr, n);
 
        Console.WriteLine("\nSorted array");
        printArr(arr, n);
    }
}
 
// This code is contributed by Ajit.


Javascript


输出:

Given array is
40 12 45 32 33 1 22
Sorted array is
1 12 22 32 33 40 45

如果范围是1到n 2怎么排序?
如果范围是1到nn 2 ,则不能直接应用上述过程,必须对其进行更改。考虑n = 100,范围从1到10000。由于基数是100,所以数字必须在0到99之间,并且数字中应该有2个数字。但是数字10000有2位以上的数字。因此,要对1到n 2范围内的数字进行排序,我们可以使用以下过程。
1)用1减去所有数字。
2)由于范围现在是0到n 2 ,因此请像上面的实现一样对计数进行两次计数。
3)元素排序后,将所有数字加1以获得原始数字。