# Can QuickSort be implemented in O(nLogn) worst case time complexity?

• Difficulty Level : Hard
• Last Updated : 08 Jan, 2021

The worst case time complexity of a typical implementation of QuickSort is O(n2). The worst case occurs when the picked pivot is always an extreme (smallest or largest) element. This happens when input array is sorted or reverse sorted and either first or last element is picked as pivot.

Although randomized QuickSort works well even when the array is sorted, there is still possible that the randomly picked element is always extreme. Can the worst case be reduced to O(nLogn)?

The answer is yes, we can achieve O(nLogn) worst case. The idea is based on the fact that the median element of an unsorted array can be found in linear time. So we find the median first, then partition the array around the median element.
Following is C++ implementation based on above idea. Most of the functions in below program are copied from K’th Smallest/Largest Element in Unsorted Array | Set 3 (Worst Case Linear Time)

## C++

 `/* A worst case O(nLogn) implementation of quicksort */` `#include` `#include` `#include` `#include` `using` `namespace` `std;`   `// Following functions are taken from http://goo.gl/ih05BF` `int` `partition(``int` `arr[], ``int` `l, ``int` `r, ``int` `k);` `int` `kthSmallest(``int` `arr[], ``int` `l, ``int` `r, ``int` `k);`   `/* A O(nLogn) time complexity function for sorting arr[l..h] */` `void` `quickSort(``int` `arr[], ``int` `l, ``int` `h)` `{` `    ``if` `(l < h)` `    ``{` `        ``// Find size of current subarray` `        ``int` `n = h-l+1;`   `        ``// Find median of arr[].` `        ``int` `med = kthSmallest(arr, l, h, n/2);`   `        ``// Partition the array around median` `        ``int` `p = partition(arr, l, h, med);`   `        ``// Recur for left and right of partition` `        ``quickSort(arr, l, p - 1);` `        ``quickSort(arr, p + 1, h);` `    ``}` `}`   `// A simple function to find median of arr[].  This is called` `// only for an array of size 5 in this program.` `int` `findMedian(``int` `arr[], ``int` `n)` `{` `    ``sort(arr, arr+n);  ``// Sort the array` `    ``return` `arr[n/2];   ``// Return middle element` `}`   `// Returns k'th smallest element in arr[l..r] in worst case` `// linear time. ASSUMPTION: ALL ELEMENTS IN ARR[] ARE DISTINCT` `int` `kthSmallest(``int` `arr[], ``int` `l, ``int` `r, ``int` `k)` `{` `    ``// If k is smaller than number of elements in array` `    ``if` `(k > 0 && k <= r - l + 1)` `    ``{` `        ``int` `n = r-l+1; ``// Number of elements in arr[l..r]`   `        ``// Divide arr[] in groups of size 5, calculate median` `        ``// of every group and store it in median[] array.` `        ``int` `i, median[(n+4)/5]; ``// There will be floor((n+4)/5) groups;` `        ``for` `(i=0; i k-1)  ``// If position is more, recur for left` `            ``return` `kthSmallest(arr, l, pos-1, k);`   `        ``// Else recur for right subarray` `        ``return` `kthSmallest(arr, pos+1, r, k-pos+l-1);` `    ``}`   `    ``// If k is more than number of elements in array` `    ``return` `INT_MAX;` `}`   `void` `swap(``int` `*a, ``int` `*b)` `{` `    ``int` `temp = *a;` `    ``*a = *b;` `    ``*b = temp;` `}`   `// It searches for x in arr[l..r], and partitions the array` `// around x.` `int` `partition(``int` `arr[], ``int` `l, ``int` `r, ``int` `x)` `{` `    ``// Search for x in arr[l..r] and move it to end` `    ``int` `i;` `    ``for` `(i=l; i

Output:

```Sorted array is
1 5 6 7 8 9 10 20 30 900 1000```

How is QuickSort implemented in practice – is above approach used?
Although worst case time complexity of the above approach is O(nLogn), it is never used in practical implementations. The hidden constants in this approach are high compared to normal Quicksort. Following are some techniques used in practical implementations of QuickSort.
1) Randomly picking up to make worst case less likely to occur (Randomized QuickSort)
2) Calling insertion sort for small sized arrays to reduce recursive calls.
3) QuickSort is tail recursive, so tail call optimizations is done.

So the approach discussed above is more of a theoretical approach with O(nLogn) worst case time complexity.