Sorting & Searching
Common sorting and searching algorithms
Last reviewed
Recommended
Sorting & Searching — Timed Test (3 questions)
No account needed. Answers and explanations arrive when you submit.
What this topic tests
The mix every Sorting & Searching set is built to, and the questions published against it so far. Nothing here is hidden before you start.
| Level | Target share | Published |
|---|---|---|
| Easy | 40% | 1 |
| Medium | 40% | 2 |
| Hard | 20% | 0 |
| Total | 3 |
Sorting & Searching — the theory
Sorting and searching are two of the most fundamental categories of algorithms in computer science, underlying countless other algorithms and everyday software operations.
Common sorting algorithms. Several sorting algorithms are commonly studied, each with different performance characteristics: bubble sort and insertion sort are simple but generally slow for large inputs; merge sort and quicksort are more efficient, generally used in practice for larger datasets; and many programming languages' built-in sort functions use optimized, hybrid approaches under the hood.
Time complexity of sorting. Understanding that different sorting algorithms have different time complexities — some scale poorly as input size grows, while others scale much better — is important context for understanding why certain algorithms are preferred for large datasets despite being more complex to implement.
Binary search. For searching within an already-sorted collection, binary search is a highly efficient technique that repeatedly divides the search range in half, comparing the target value against the middle element and eliminating half of the remaining possibilities each time, rather than checking every element sequentially.
When sorting helps searching. Many problems become much easier to solve efficiently once the input is sorted — for example, binary search only works on sorted data, and various other algorithms rely on a sorted input as a precondition for their efficiency, which is why sorting is often a first step even when the eventual goal is a different operation entirely.
Stability and other sorting properties. Some sorting algorithms are "stable," meaning elements with equal values retain their relative original order after sorting — a property that matters in certain applications where the original order of equal elements carries meaning.
The numbers behind the comparisons. Putting concrete complexities to the algorithms makes the comparison sharper: bubble sort and insertion sort are O(n²) in the average and worst cases, merge sort is O(n log n) in all cases, and quicksort is O(n log n) on average but degrades to O(n²) on adversarial input if pivots are chosen poorly. Insertion sort is nonetheless genuinely fast on small or nearly sorted inputs, which is why production sorts often switch to it for small subranges. Binary search runs in O(log n), which is why it remains fast even as inputs grow enormous — doubling the data adds a single step.
Why O(n log n) is the barrier. Any sorting algorithm that works by comparing pairs of elements cannot do better than O(n log n) in the worst case. The reasoning is counting-based: there are n! possible orderings, each comparison distinguishes at most two branches, and distinguishing n! possibilities therefore requires at least on the order of log(n!) comparisons, which grows as n log n. This is not a limitation of current algorithms but a proven lower bound on the whole approach, which is why no comparison sort will ever be asymptotically faster.
Sorting without comparisons. The bound above applies only to comparison-based sorting, and algorithms that exploit structure in the keys can beat it. Counting sort tallies occurrences of each value and reconstructs the output, running in time proportional to the number of elements plus the range of values; radix sort processes keys digit by digit. Both are linear under the right conditions and useless under the wrong ones — counting sort over a huge value range consumes memory proportional to that range. They illustrate a general principle: knowing something about your data can beat a general-purpose algorithm.
Memory use and stability in practice. Merge sort's guaranteed O(n log n) comes at the cost of O(n) auxiliary memory, while quicksort sorts in place with only logarithmic stack space — a trade-off that often decides which is used where memory is constrained. Stability interacts with this: merge sort is naturally stable, quicksort is not. Stability matters concretely when sorting by successive keys, since sorting by a secondary key and then stably by a primary key produces a correctly ordered result on both, an idiom that silently breaks with an unstable sort.
Binary search beyond sorted arrays. The technique generalizes well past "find this value in this array". Variants find the first or last occurrence of a repeated value, or the insertion point for a value not present. More powerfully, binary search applies to any monotonic predicate — if some property is false up to a threshold and true after it, the threshold can be found in logarithmic time without any array existing at all. This pattern, often called binary searching on the answer, turns many optimization problems ("what is the smallest capacity that works?") into a feasibility check repeated a logarithmic number of times.
Getting binary search right. Binary search is notoriously easy to state and easy to implement incorrectly. The failures are boundary conditions: whether the search range is inclusive or exclusive at each end, whether the midpoint calculation can overflow in fixed-width integer types, and whether each iteration is guaranteed to shrink the range — a loop that fails to make progress hangs rather than returning a wrong answer. The discipline that prevents these is stating the loop invariant explicitly, then verifying by hand on arrays of length zero, one, and two.
What to do in practice. For nearly all production work the correct choice is the language's built-in sort, which is a carefully tuned hybrid that beats a hand-written implementation on both performance and correctness. The skill that transfers is not implementing sorts but knowing what to ask: is the comparator correct and consistent, is stability required, is the input already nearly sorted, and is sorting even necessary — since finding a maximum or the top few elements can be done in linear time without sorting at all.
Understanding both how common sorting algorithms work and when binary search applies is foundational to reasoning about the efficiency of a wide range of other algorithms and data-processing tasks.
Sample questions
Three questions from this topic, with the answer and the reasoning shown.
Q1EasyWhat is a key requirement for binary search to work correctly?
- The collection must already be sortedCorrect
- The collection must contain exactly one element
- The collection must be unsorted
- The collection must only contain text values
Explanation
The halving is only sound because the data is ordered. Sorted order is what lets one comparison speak for a whole half of the array: if the middle element already exceeds the target, every element after it exceeds the target too, so that half can go without being looked at. Strip the ordering away and that inference is simply false, which is why NIST's definition opens with a sorted array rather than mentioning it as an aside.
Handed unsorted data, binary search does not complain. It applies the same rule, walks into the wrong half, and reports the value missing or returns a meaningless index. A wrong answer with no error attached is the expensive kind, because nothing in the run points at the cause. Python's bisect functions document the same assumption. Sorting first costs more than one scan, so binary search pays off when the same collection is searched many times.
Size is beside the point: empty ranges and huge ones both work, so one element is no requirement. Unsorted inverts the actual condition. Element type is open as well, since anything with a consistent ordering will do.
Q2MediumHow does binary search reduce the search space at each step?
- By comparing the target against the middle element and eliminating half the remaining possibilitiesCorrect
- By checking every single element one at a time from the start
- By randomly guessing an index each time
- By sorting the array again at every step
Explanation
Each step looks at exactly one element, the middle of the interval still in play, and uses that single comparison to throw away everything on one side. If the target is smaller than the middle value it cannot sit to the right of it, so the whole upper half goes; if it is larger, the lower half goes. NIST describes the loop that way: narrow to one half, then repeat until the value turns up or the interval empties.
Halving is what buys the running time. A million sorted entries collapse to one in about twenty comparisons. The detail that surfaces in code review is the midpoint. Writing mid = (high + low) / 2 overflows once the indices approach the largest representable integer; mid = low + (high - low) / 2 computes the same value and never overflows.
Checking every element from the start is linear search, correct but O(n), and exactly what binary search avoids. A random probe discards nothing reliably, because it gives no rule for which side to keep. Re-sorting each step would cost more than the entire search.
Q3MediumWhat does it mean for a sorting algorithm to be 'stable'?
- Elements with equal values retain their relative original order after sortingCorrect
- The algorithm never makes any comparisons
- The algorithm always runs in constant time
- The algorithm cannot sort more than 10 elements
Explanation
Stability is a promise about ties, and only about ties. When two records compare equal on the sort key, a stable sort leaves them in the order they arrived; an unstable one is free to swap them. NIST states the definition in exactly those terms, and Python guarantees it for sorted and list.sort.
The payoff shows up when one sort is not enough. To list students by descending grade and, within each grade, by ascending age, sort on age first and then sort on grade. The second pass only moves records whose grades differ, so the age ordering survives inside every grade group. That two-pass idiom is the reason the guarantee is worth writing down. Radix sort leans on the same property: each digit pass must be stable or the earlier passes are undone.
The other options describe things stability is not. A sort making no comparisons would say nothing about how ties are ordered. Constant running time is a complexity claim, unreachable for a comparison sort, and unrelated to ordering. Nothing about stability caps how many elements a sort accepts.
Practise all 3 questions
Every published question in Sorting & Searching, with its answer and explanation.