简体   繁体   English

Arrays.sort()会不会增加时间复杂度和空间时间复杂度?

[英]Will Arrays.sort() increase time complexity and space time complexity?

There is an array related problem, the requirement is that time complexity is O(n) and space complexity is O(1).有个数组相关的问题,要求时间复杂度O(n),空间复杂度O(1)。

If I use Arrays.sort(arr) , and use a for loop to one pass loop, for example:如果我使用Arrays.sort(arr) ,并使用for循环来一次循环,例如:

public static int hello(int[]A){
  Arrays.sort(A);
  for(int i=0;i<A.length;i++){
     ....................
  }
  return ....;

} }

So the loop will cost O(n) time.所以循环将花费 O(n) 时间。 My question is: will Arrays.sort() cost more time?我的问题是: Arrays.sort()会花费更多时间吗? If I use Arrays.sort() , will this time complexity still be O(n)?如果我使用Arrays.sort() ,这个时间复杂度还是 O(n) 吗? And will Arrays.sort() cost more space? Arrays.sort()会占用更多空间吗?

I am assuming you are talking about Java here.我假设您在这里谈论的是 Java。

So the loop will cost O(n) time, my question is that will Arrays.sort() cost more time?所以循环将花费 O(n) 时间,我的问题是 Arrays.sort() 会花费更多时间吗?

Yes , Arrays.sort(int[]) in all Java standard library implementations that I know, is an example of a comparison-based sort and thus must have worst-case complexity Ω(n log n) .是的,我知道的所有 Java 标准库实现中的Arrays.sort(int[])都是基于比较的排序的一个例子,因此必须具有最坏情况复杂度 Ω(n log n) In particular, Oracle Java 7 uses a dual-pivot quicksort variant for the integer overloads, which actually has an Ω(n 2 ) worst case.特别是,Oracle Java 7 对整数重载使用双枢轴快速排序变体,它实际上具有Ω(n 2 )最坏情况。

and will Arrays.sort() cost more space? Arrays.sort() 会占用更多空间吗?

In all likelihood it will use ω(1) space (which means another yes , the space usage is not O(1)).它很可能会使用 ω(1) 空间(这意味着另一个,空间使用不是 O(1))。 While it's not impossible to implement a comparison-based sort with only constant extra space, it's highly impractical.虽然仅使用恒定的额外空间来实现基于比较的排序并非不可能,但这是非常不切实际的。

That said, under certain conditions it is possible to sort specific types of data in linear time, see for example:也就是说,在某些条件下,可以在线性时间内对特定类型的数据进行排序,例如:

With a constant range of input integers (for example if abs(A[i]) <= C for some constant C), then counting sort and radix sort use indeed only O(n) time and O(1) space, so that might be useful.对于恒定范围的输入整数(例如,如果abs(A[i]) <= C表示某个常量 C),那么计数排序和基数排序实际上仅使用 O(n) 时间和 O(1) 空间,因此可能有用。

According to the java jvm 8 javadocs of Arrays.sort() method:根据 Arrays.sort() 方法的 java jvm 8 javadocs:

The sorting algorithm is a Dual-Pivot Quicksort by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch.排序算法是 Vladimir Yaroslavskiy、Jon Bentley 和 Joshua Bloch 的双枢轴快速排序。 This algorithm offers O(n log(n)) performance on many data sets that cause other quicksorts to degrade to quadratic performance, and is typically faster than traditional (one-pivot) Quicksort implementations.该算法在许多数据集上提供 O(n log(n)) 性能,导致其他快速排序降级为二次性能,并且通常比传统(单轴)快速排序实现更快。

So it will increase your time complexity from O(n) to O(n log(n))所以它会将你的时间复杂度从 O(n) 增加到 O(n log(n))

It is more than O(n) time and requires more than O(1) space.它的时间超过 O(n) 并且需要超过 O(1) 的空间。

Arrays.sort() utilizes a modified Timsort in 1.7 which is a relatively recently developed sorting algorithm and it offers sorting with complexity x where O(n)< x < O(nlgn) and space of O(n/2) Arrays.sort()使用了 1.7 中的修改Timsort ,这是一种相对较新开发的排序算法,它提供复杂度为 x 的排序,其中 O(n)< x < O(nlgn) 和空间为 O(n/2)

最近 JDK 中的 Arrays.sort(int[] a) 是用双枢轴快速排序算法实现的,该算法具有 O(n log n) 平均复杂度并且就地执行(例如不需要额外的空间)。

Since you're talking about it in Java Language, the time complexity will surely increase from O(n) to O(nlogn).既然你用Java语言谈论它,时间复杂度肯定会从O(n)增加到O(nlogn)。 That's because in Java 8, Arrays.sort() is implemented in Dual-pivot quicksort algorithm, not single pivot .那是因为在 Java 8 中, Arrays.sort() 是在 Dual-pivot quicksort 算法中实现的,而不是 single pivot 。 So it requires extra time.所以需要额外的时间。 And space complexity of O(1) is not possible , since it requires more space, I guess O(n/2). O(1) 的空间复杂度是不可能的,因为它需要更多的空间,我猜 O(n/2)。

Arrays.sort(int[]) Arrays.sort(int[])

As well as Arrays.sort(long[]), Arrays.sort(float[]) and Arrays.sort(double[])以及 Arrays.sort(long[])、Arrays.sort(float[]) 和 Arrays.sort(double[])

Time complexity时间复杂度

Time complexity of Arrays.sort(int[]) depends on the version of Java. Arrays.sort(int[])的时间复杂度取决于 Java 的版本。

O(n 2 ) prior to Java 14 O(n 2 ) 在 Java 之前 14

A pretty ordinary quicksort was used with time complexity ranging from O(n) (when the array is already sorted and we are only checking that it is) to O(n 2 ) for certain inputs that cause extremely uneven distribution of elements into parts with an average complexity of O(n log(n)) .使用了一个非常普通的快速排序,时间复杂度从 O(n) (当数组已经排序并且我们只是检查它是)到 O(n 2 )对于某些输入导致元素极不均匀分布到部分O(n log(n)) 的平均复杂度 You can find a detailed analysis here .您可以在此处找到详细分析。

O(n log(n)) starting from Java 14 O(n log(n)) 从 Java 开始 14

In Java 14 the implementation was improved to guarantee the worst-case time complexity of O(n log(n)) .在 Java 14 中,改进了实现以保证O(n log(n)) 的最坏情况时间复杂度 The function was changed to resort to heapsort if recursion becomes too deep:如果递归变得太深,function 被更改求助于堆排序

if ((bits += DELTA) > MAX_RECURSION_DEPTH) {
  heapSort(a, low, high);
  return;
}

which prevents the method from degrading to quadratic time complexity.这可以防止该方法退化为二次时间复杂度。

Glimpse into the future瞥见未来

There is an initiative to switch to radix sort for almost random big enough arrays thus reducing the time complexity to O(n) in the worst-case .有一项举措是针对几乎随机的足够大的 arrays 切换到基数排序,从而在最坏情况下将时间复杂度降低到 O(n)

O(n) space O(n) 空间

In all versions, the algorithm has space complexity ranging from O(1) (when the array is already sorted and we only to check that it is) to O(n) (when the array is highly structured (there is a small number of sorted subarrays inside the original array and we merge those subarrays)).在所有版本中,该算法的空间复杂度从 O(1) (当数组已经排序并且我们只检查它是否排序时)到 O(n) (当数组高度结构化(有少量在原始数组中排序子数组,然后我们合并这些子数组))。

Here's where allocation happens in the worst case:这是最坏情况下发生分配的地方:

/*
 * Merge runs of highly structured array.
 */
if (count > 1) {
  int[] b; int offset = low;

  if (sorter == null || (b = (int[]) sorter.b) == null) {
    b = new int[size];
  } else {
    offset = sorter.offset;
  }
  mergeRuns(a, b, offset, 1, sorter != null, run, 0, count);
}
return true;

DualPivotQuicksort.java DualPivotQuicksort.java

While the question asks specifically about Arrays.sort(int[]) method I still decided to include answers for other data types since this is the first result when you look for Arrays.sort() time and space complexity in Google and it is not easy to find correct answers to this simple question in other places.虽然这个问题专门询问 Arrays.sort(int[]) 方法,但我仍然决定包括其他数据类型的答案,因为这是您在 Google 中查找 Arrays.sort() 时间和空间复杂度时的第一个结果,它不是在其他地方很容易找到这个简单问题的正确答案。

Arrays.sort(short[]) Arrays.sort(短[])

As well as Arrays.sort(char[]) and Arrays.sort(byte[])以及 Arrays.sort(char[]) 和 Arrays.sort(byte[])

O(n) time, O(1) space O(n) 时间,O(1) 空间

Although the documentation says:尽管文档说:

The sorting algorithm is a Dual-Pivot Quicksort by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch.排序算法是 Vladimir Yaroslavskiy、Jon Bentley 和 Joshua Bloch 的双轴快速排序。 This algorithm offers O(n log(n)) performance on all data sets, and is typically faster than traditional (one-pivot) Quicksort implementations.该算法在所有数据集上提供 O(n log(n)) 性能,并且通常比传统(单轴)快速排序实现更快。

This is not true at least starting from Java 7. Actually, an in-place counting sort used for big enough arrays, which has linear time complexity and constant space complexity :这至少从 Java 开始是不正确的 7. 实际上,一个就地计数排序用于足够大的 arrays,它具有线性时间复杂度恒定空间复杂度

private static void countingSort(short[] a, int low, int high) {
    int[] count = new int[NUM_SHORT_VALUES];

    /*
     * Compute a histogram with the number of each values.
     */
    for (int i = high; i > low; ++count[a[--i] & 0xFFFF]);

    /*
     * Place values on their final positions.
     */
    if (high - low > NUM_SHORT_VALUES) {
        for (int i = MAX_SHORT_INDEX; --i > Short.MAX_VALUE; ) {
            int value = i & 0xFFFF;

            for (low = high - count[value]; high > low;
                a[--high] = (short) value
            );
        }
    } else {
        for (int i = MAX_SHORT_INDEX; high > low; ) {
            while (count[--i & 0xFFFF] == 0);

            int value = i & 0xFFFF;
            int c = count[value];

            do {
                a[--high] = (short) value;
            } while (--c > 0);
        }
    }
}

Counting sort implementation 计数排序实现

Arrays.sort(Object[]) Arrays.sort(对象[])

Unlike other methods, this one is well-documented and the documentation here corresponds to reality.与其他方法不同,此方法有据可查,此处的文档与现实相对应。

O(n log(n)) time O(n log(n)) 时间

Starting from Java 7从 Java 开始 7

This implementation is a stable, adaptive, iterative mergesort that requires far fewer than n lg(n) comparisons when the input array is partially sorted, while offering the performance of a traditional mergesort when the input array is randomly ordered.此实现是一种稳定的、自适应的、迭代的合并排序,当输入数组部分排序时需要的比较少于 n lg(n) 次,同时在输入数组随机排序时提供传统合并排序的性能。 If the input array is nearly sorted, the implementation requires approximately n comparisons.如果输入数组几乎已排序,则实现需要大约 n 次比较。

https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[]) https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[])

Before Java 7之前 Java 7

The sorting algorithm is a modified mergesort (in which the merge is omitted if the highest element in the low sublist is less than the lowest element in the high sublist).排序算法是修改后的合并排序(如果低子列表中的最高元素小于高子列表中的最低元素,则合并被省略)。 This algorithm offers guaranteed n*log(n) performance.该算法提供有保证的 n*log(n) 性能。

https://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort(java.lang.Object[]) https://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html#sort(java.lang.Object[])

O(n) space O(n) 空间

Starting from Java 7从 Java 开始 7

Temporary storage requirements vary from a small constant for nearly sorted input arrays to n/2 object references for randomly ordered input arrays.临时存储要求从几乎排序的输入 arrays 的小常量到随机排序的输入 arrays 的 n/2 object 引用不等。

https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[]) https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[])

Before Java 7之前 Java 7

The algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort to sort object references is a "modified mergesort (in which the merge is omitted if the highest element in the low sublist is less than the lowest element in the high sublist)." java.util.Arrays.sort 和(间接)java.util.Collections.sort 对 object 引用使用的算法是“修改后的合并排序(如果低子列表中的最高元素小于高子列表中的最低元素)。” It is a reasonably fast stable sort that guarantees O(n log n) performance and requires O(n) extra space.它是一种相当快的稳定排序,可保证 O(n log n) 的性能并需要 O(n) 的额外空间。

https://bugs.openjdk.org/browse/JDK-6804124 https://bugs.openjdk.org/browse/JDK-6804124

import java.util.Arrays;
public class MyClass {
    
    
    static void hello(int ac[]){
        
    }
    
    public static void main(String args[]) {
  
      int ac[] ={1,4,2,3,5};
    
       int i=0;
       int temp=0;
       
       while(i!=5-1){
            if( ac[i]>ac[i+1]){
               temp= ac[i];
               ac[i]=ac[i+1];
               ac[i+1]=temp;
               i= -1;
           }
           
          i++;
       }
       
      System.out.println(Arrays.toString(ac));



    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM