I'm working with QuickSort and I tested these 2 algorithms on LeetCode for this problem. Both algorithms work, but one seems to be significantly faster than the other one and I don't understand why.
This one exceeds time limit of LeetCode:
function quickSort(array) {
quickSortHelper(array, 0, array.length - 1);
return array;
}
function quickSortHelper(array, start, end) {
// Edge case
if(start >= end) return;
// Always choose the pivot index at the beginning of the array.
const pivot = start;
// The left index is next to the pivot on the right.
let left = start + 1;
let right = end;
while (right >= left) {
if (array[left] > array[right] && array[right] < array[pivot])
swap(left, right, array);
if (array[left] < array[pivot]) left += 1;
if (array[right] > array[pivot]) right -= 1;
}
swap(pivot, right, array);
// Always sort the smaller sub-array first
const leftIsSmaller = right - 1 - start < end - (right + 1);
if (leftIsSmaller) {
quickSort(array, start, right - 1);
quickSort(array, right + 1, end);
}
else {
quickSort(array, right + 1, end);
quickSort(array, start, right - 1);
}
}
function swap(a, b, array) {
[array[a], array[b]] = [array[b], array[a]];
return array;
}
Big O:
- Worst: Time = O(n^2) because if the pivot keeps being swapped to the end of the unsorted part, then we have O(n - 1) ~ O(n) every time = O(n*n)
- Best: Time = O(nlog(n)) when the pivot devides the array into 2 halves.
- Average: Time = O(nlog(n))
- Space = O(log(n)) because recursion in place with 2 sub-arrays and quicksort against the smaller sub-array first.
This one doesn't exceed LeetCode time limit and it's significantly faster than most of the submissions. The 2 while loops inside the big while loop (to me) seem to be slower but it's actually faster.
function quickSort(array) {
sortHelper(array, 0, array.length - 1);
return array;
}
function sortHelper(array, start, end) {
if (start >= end) return;
let i = start;
let j = end;
let base = array[i];
while (i < j) {
while (i < j && array[j] >= base) j -= 1; // This makes sense but why this while loop has to happen before the other while loop?
array[i] = array[j]; // this line
while (i < j && array[i] <= base) i += 1;
array[j] = array[i]; // and this line. don't they make you lose access to the values in the array?
}
array[i] = base;
sortHelper(array, start, i - 1);
sortHelper(array, i + 1, end);
}
Why is that?