📜  Java |使用Arrays.sort()函数处理TLE

📅  最后修改于: 2021-06-26 20:02:33             🧑  作者: Mango

在编程中,如果Java程序员不小心使用Arrays.sort()函数,则通常面临超过或超过TLE的时间限制。

下面的Java代码显示了琐碎的Arrays.sort()函数所花费的运行时间。

// Java program to show
// time taken by trivial Arrays.sort function
  
import java.util.Arrays;
import java.util.Calendar;
  
public class ArraySort {
  
    // function to fill array with values
    void fill(int a[], int n)
    {
        for (int i = 0; i < n; i++)
            a[i] = i + 1;
    }
  
    // function to check the performance
    // of trivial Arrays.sort() function
    void performanceCheckOfSorting()
    {
        // creating a class object
        ArraySort obj = new ArraySort();
  
        // variables to store start
        // and end of operation
        long startTime = 0l;
        long endTime = 0l;
        int array1[] = new int[100000];
        int n = array1.length;
  
        // calling function to fill array with
        // values
        obj.fill(array1, n);
  
        startTime = Calendar.getInstance()
                        .getTimeInMillis();
        // sorting the obtained array
        Arrays.sort(array1);
        endTime = Calendar.getInstance()
                      .getTimeInMillis();
  
        // printing the total time taken
        // by Arrays.sort in worst case
        System.out.println("Time Taken By The"
                           + " Use of Trivial "
                           + "Arrays.sort() function : "
                           + (endTime - startTime)
                           + "ms");
    }
  
    // Driver function
    public static void main(String args[])
    {
        // creating object of class
        ArraySort obj = new ArraySort();
  
        // calling function to compare performance
        obj.performanceCheckOfSorting();
    }
}
输出:
Time Taken By The Use of Trivial Arrays.sort() function : 31ms

正如我们所看到的,对一百万个数字进行排序所花费的时间非常安静,乍一看似乎不太高,但是在编程竞赛中,每毫秒都会带来不同。

标题的原因:
Arrays.sort()函数在其实现中使用快速排序。快速排序的最坏情况复杂度是O( N^2 ),其中N是数组的大小。最坏情况的复杂性发生在已经对输入数组进行排序并且大多数时间问题设置者喜欢进行此类测试用例的情况下。

如何处理最坏的情况:

  1. 使用对象数组(基元的包装器类)代替值:
    与使用值数组不同,对对象数组进行排序的时间更少。这是因为Arrays.sort()函数使用Merge Sort对对象数组进行排序,这在最坏情况下的复杂度为O( NlogN )与快速排序的O( N^2 )。

    下面的Java代码显示了在值数组上使用Arrays.sort()函数与在对象数组上使用Arrays.sort()函数之间的运行时比较。

    // Java program to handle worst case
    // of Arrays.sort method
      
    import java.util.Arrays;
    import java.util.Calendar;
      
    public class ArraySort {
      
        // function to fill array with values
        void fill(int a[], int n)
        {
            for (int i = 0; i < n; i++)
                a[i] = i + 1;
        }
      
        // function to fill array with
        // objects
        void fill2(Integer a[], int n)
        {
            for (int i = 0; i < n; i++)
                a[i] = new Integer(i + 1);
        }
      
        // function to compare performance
        // of original and optimized method 1
        void performanceCheckOfSorting()
        {
            // creating a class object
            ArraySort obj = new ArraySort();
      
            // variables to store start
            // and end of operation
            long startTime = 0l;
            long endTime = 0l;
      
            // Method 1
            // Using Arrays.sort()
            int array1[] = new int[100000];
            int n = array1.length;
      
            // calling function to fill array with
            // values
            obj.fill(array1, n);
      
            startTime = Calendar.getInstance()
                            .getTimeInMillis();
            // sorting the obtained array
            Arrays.sort(array1);
            endTime = Calendar.getInstance()
                          .getTimeInMillis();
      
            // printing the total time taken
            // by Arrays.sort in worst case
            System.out.println("Time Taken By Arrays.sort"
                               + " Method On Values : "
                               + (endTime - startTime)
                               + "ms");
      
            // Method 2
            // Taking Array Of Type Object
            Integer array2[] = new Integer[n];
      
            // calling function to fill array with
            // objects of class Integer
            obj.fill2(array2, n);
      
            startTime = Calendar.getInstance()
                            .getTimeInMillis();
            Arrays.sort(array2);
            endTime = Calendar.getInstance()
                          .getTimeInMillis();
      
            // printing the total time taken
            // by Arrays.sort in case of object array
            System.out.println("Time Taken By Arrays.sort"
                               + " Method On Objects: "
                               + (endTime - startTime)
                               + "ms");
        }
      
        // Driver function
        public static void main(String args[])
        {
            // creating object of class
            ArraySort obj = new ArraySort();
      
            // calling function to compare performance
            obj.performanceCheckOfSorting();
        }
    }
    
    输出:
    Time Taken By Arrays.sort Method On Values : 31ms
    Time Taken By Arrays.sort Method On Objects : 19ms
    

    在这里我们可以看到Arrays.sort()函数对对象数组进行排序所花费的时间少于值数组。

  2. 排序前混洗:
    这种方法是竞争Java程序员最常使用的方法。想法是改组整个输入数组
    在排序之前,以这种方式处理在已排序数组的情况下出现的最坏的快速排序情况。
    这种方法的另一个好处是,它保持了数组的原始性质。

    在下面的Java程序中,我展示了对Arrays.sort()函数的平凡使用与将整个数组改组后的平凡使用之间的比较。我还提供了用户定义的随机播放方法的实现,其复杂度为O( N ),其中N是数组的大小。

    // Java program to handle worst-case
    // of Arrays.sort method
      
    import java.util.Arrays;
    import java.util.Calendar;
      
    public class ArraySort {
      
        // function to fill array with values
        void fill(int a[], int n)
        {
            for (int i = 0; i < n; i++)
                a[i] = i + 1;
        }
      
        // Java implementation of shuffle
        // function
        void shuffle(int a[], int n)
        {
            for (int i = 0; i < n; i++) {
      
                // getting the random index
                int t = (int)Math.random() * a.length;
      
                // and swapping values a random index
                // with the current index
                int x = a[t];
                a[t] = a[i];
                a[i] = x;
            }
        }
      
        // function to compare performance
        // of original and optimized method 2
        void performanceCheckOfSorting()
        {
            // creating a class object
            ArraySort obj = new ArraySort();
      
            // variables to store start
            // and end of operation
            long startTime = 0l;
            long endTime = 0l;
      
            // Using Arrays.sort()
            // without shuffling before sorting
            int array1[] = new int[100000];
            int n = array1.length;
      
            // calling function to fill array with
            // values
            obj.fill(array1, n);
      
            startTime = Calendar.getInstance()
                            .getTimeInMillis();
            // sorting the obtained array
            Arrays.sort(array1);
            endTime = Calendar.getInstance()
                          .getTimeInMillis();
      
            // printing the total time taken
            // by Arrays.sort in worst case
            System.out.println("Time Taken By Arrays.sort"
                               + " Method On Trivial Use: "
                               + (endTime - startTime)
                               + "ms");
      
            // Shuffling before Sorting
            // calling function to fill array with
            // values
            obj.fill(array1, n);
      
            // calling function to shuffle
            // obtained array
            obj.shuffle(array1, n);
      
            startTime = Calendar.getInstance()
                            .getTimeInMillis();
            Arrays.sort(array1);
            endTime = Calendar.getInstance()
                          .getTimeInMillis();
      
            // printing the total time taken
            // by Arrays.sort() function in case shuffling
            // of shuffling before sorting
            System.out.println("Time Taken By Arrays.sort"
                               + " Method After Shuffling "
                               + "Before Sorting : "
                               + (endTime - startTime)
                               + "ms");
        }
      
        // Driver function
        public static void main(String args[])
        {
            // creating object of class
            ArraySort obj = new ArraySort();
      
            // calling function to compare performance
            obj.performanceCheckOfSorting();
        }
    }
    
    输出:
    Time Taken By Arrays.sort() Function On Trivial Use : 31ms
    Time Taken By Arrays.sort() Function After Shuffling Before Sorting : 10ms
    

    在这里,在这种情况下,我们看到,与未重组数组相比,在重组数组上使用Arrays.sort()函数花费的时间更少。而且,对对象数组进行排序所花费的时间比在改组后对数组进行排序所花费的时间更长。

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。