Lesson

Implement a function called `quickSort`

that takes an array of integers and sorts it in ascending order using the quicksort algorithm. The quicksort algorithm is a divide and conquer algorithm that works by selecting a pivot element and partitioning the other elements in the array around the pivot. The pivot can be selected in many different ways, including selecting the first, last, middle, or a random element as the pivot. In this implementation, you should select the last element as the pivot. The quicksort function should use recursion to sort the left and right subarrays created by partitioning the original array around the pivot. You should also implement two helper functions, partition and swap, to help with the implementation of the quicksort function.```
Input: [9, 8, 3, 6, 4]
Output: [3, 4, 6, 8, 9]
```

The quicksort algorithm is a well-known sorting algorithm that works by dividing the problem into subproblems and solving them recursively. The idea behind quicksort is to select a pivot element, partition the array around the pivot, and then recursively sort the subarrays that were created by partitioning.

The quickSort function can be implemented using the following steps:

Check if the start index is less than the end index.

If so, select the last element of the array as the pivot element.

Call the partition function to partition the array around the pivot.

Recursively call the quickSort function on the left and right subarrays created by partitioning.

Return the sorted array.

The partition function can be implemented as follows:

Store the start index in a variable x.

Loop through the array from the start index to the end index.

If the current element is less than the pivot, swap the current element with the element at index x and increment x.

After the loop, swap the pivot element with the element at index x.

Return the index x.

The swap function can be implemented as follows:

Store the element at index i in a variable temp.

Set the element at index i to the element at index j.

Set the element at index j to temp.

Here's the implementation of the quickSort function in JavaScript:

```
function quickSort(arr, start = 0, end = arr.length - 1) {
if (start < end) {
const pivotIndex = partition(arr, start, end);
quickSort(arr, start, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, end);
}
return arr;
}
function partition(arr, start, end) {
const pivot = arr[end];
let x = start;
for (let i = start; i < end; i++) {
if (arr[i] < pivot) {
swap(arr, i, x);
x++;
}
}
swap(arr, x, end);
return x;
}
function swap(arr, i, j) {
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
```

**Big O Complexity Analysis:**
The quicksort algorithm is known for its efficiency and is often used in practice for sorting large data sets. The average time complexity of quicksort is O(n*log n), where n is the number of elements in the array to be sorted. This time complexity occurs on average when the pivot element is selected in such a way that it partitions the array into two subarrays of roughly equal size.

The worst-case time complexity of quicksort is O(n^2), which occurs when the pivot element is always chosen as the smallest or largest element in the array. In this case, the partition function will always partition the array into a subarray of size one and a subarray of size n-1, resulting in n recursive calls to quicksort. This worst-case scenario can be avoided by selecting the pivot element randomly or by using a more sophisticated pivot selection algorithm.

In terms of space complexity, quicksort has an average case of O(log n), which occurs because the algorithm sorts the subarrays in place, without requiring additional memory allocation. In the worst case, however, the space complexity can be O(n), which occurs when the recursion depth is n.

Overall, the quicksort algorithm is a very efficient sorting algorithm in practice, with an average time complexity of O(n*log n) and an average space complexity of O(log n). The worst-case time complexity of O(n^2) is rare in practice and can be avoided by selecting the pivot element wisely.