Quick Sort Algorithm in DSA Javascript - Time & Space Complexity
We want to understand how the time to sort a list with Quick Sort changes as the list gets bigger.
How does the number of steps grow when the input size increases?
Analyze the time complexity of the following code snippet.
function quickSort(arr) {
if (arr.length <= 1) return arr;
const pivot = arr[arr.length - 1];
const left = [];
const right = [];
for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] < pivot) left.push(arr[i]);
else right.push(arr[i]);
}
return [...quickSort(left), pivot, ...quickSort(right)];
}
This code sorts an array by picking a pivot, splitting the array into smaller parts, and sorting those parts recursively.
- Primary operation: The for-loop that compares each element to the pivot to split the array.
- How many times: This loop runs once for each element in the current array segment, repeated recursively on smaller parts.
- Recursion: The function calls itself twice on smaller arrays (left and right), repeating the splitting and sorting.
When the array size doubles, the number of comparisons grows roughly by a bit more than double because of the recursive splitting.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 30 comparisons |
| 100 | About 700 comparisons |
| 1000 | About 10,000 comparisons |
Pattern observation: The operations grow faster than the input size but slower than the square of the input size.
Time Complexity: O(n log n)
This means that as the list gets bigger, the time to sort grows a little faster than the size but much slower than checking every pair.
[X] Wrong: "Quick Sort always takes the same time regardless of input order."
[OK] Correct: The time depends on how balanced the splits are; if the pivot is always the smallest or largest, it takes longer.
Understanding Quick Sort's time complexity helps you explain why it is fast on average and what cases slow it down, showing your grasp of sorting efficiency.
"What if we always picked the middle element as the pivot? How would the time complexity change?"
Practice
Quick Sort algorithm?Solution
Step 1: Understand Quick Sort's approach
Quick Sort picks a pivot element and divides the array into parts smaller and larger than the pivot.Step 2: Recursive sorting of parts
It then sorts these parts by calling itself recursively until the whole array is sorted.Final Answer:
Divide the array into smaller parts using a pivot and sort them recursively -> Option CQuick Check:
Quick Sort = Divide and conquer [OK]
- Thinking Quick Sort compares all pairs directly
- Confusing Quick Sort with Selection Sort
- Believing Quick Sort merges arrays like Merge Sort
arr[i] and arr[j] in JavaScript during Quick Sort?Solution
Step 1: Identify correct swap method in JavaScript
JavaScript does not support tuple unpacking like Python, so swapping requires a temporary variable.Step 2: Check each option
temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; uses a temporary variable to swap correctly. arr[i], arr[j] = arr[j], arr[i]; is Python syntax, swap(arr[i], arr[j]); is undefined, arr[i] = arr[j]; arr[j] = arr[i]; overwrites values incorrectly.Final Answer:
temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; -> Option BQuick Check:
Swap with temp variable = temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; [OK]
- Using Python-style tuple swap in JavaScript
- Overwriting one element before saving it
- Calling undefined swap function
[4, 2, 7, 1] with pivot as the last element?function partition(arr, low, high) {
let pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;
}
}
let temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp;
return i + 1;
}
let arr = [4, 2, 7, 1];
let pi = partition(arr, 0, arr.length - 1);
console.log(arr);Solution
Step 1: Trace the partition loop
Pivot = 1. Loop checks elements less than 1. No elements are less, so i stays at -1.Step 2: Swap pivot with element at i+1
Swap arr[0] and arr[3]: 4 and 1 swap places. Array becomes [1, 2, 7, 4].Final Answer:
[1, 2, 7, 4] -> Option AQuick Check:
Pivot 1 placed at start, others unchanged [OK]
- Assuming pivot stays at end
- Swapping wrong elements after loop
- Not updating i correctly
function partition(arr, low, high) {
let pivot = arr[low];
let i = low + 1;
for (let j = low + 1; j <= high; j++) {
if (arr[j] <= pivot) {
let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;
i++;
}
}
let temp = arr[low]; arr[low] = arr[i]; arr[i] = temp;
return i;
}Solution
Step 1: Understand pivot placement
Pivot is arr[low]. After loop, pivot must be placed at correct position.Step 2: Check swap of pivot with arr[i]
Variable i points to next greater element, so pivot should swap with arr[i - 1], not arr[i].Final Answer:
Swapping pivot with arr[i] should be with arr[i - 1] -> Option DQuick Check:
Pivot swap index off by one [OK]
- Swapping pivot with wrong index
- Confusing pivot position in array
- Changing loop start incorrectly
Solution
Step 1: Understand pivot selection strategies
Choosing first or last can lead to worst-case O(n^2) on sorted arrays. Middle element alone may not be representative.Step 2: Best strategy for balance
Median-of-three selects a pivot likely closer to the array's true median, promoting balanced partitions and average O(n log n) performance.Final Answer:
Choosing the median of first, middle, and last elements as pivot -> Option AQuick Check:
Median-of-three pivot = balanced partitions [OK]
- Always picking first or last element as pivot
- Ignoring pivot choice impact on performance
- Assuming middle element is always best pivot
Ready to prove it?
Pass the test and this pattern moves unknown
