3.1.3 · D4Complexity Analysis

Exercises — Best, worst, average case — with examples

2,815 words13 min readBack to topic

Before we start, one shared toolbox we will lean on again and again:


Level 1 — Recognition

L1.1

For a fixed input size , which of best / worst / average is defined as ? Which is ?

Recall Solution

= number of operations on input .

  • = "the smallest such value over all inputs of that size" = least work = best case, .
  • = "the largest such value over all inputs of that size" = most work = worst case, .

L1.2

True or false: "For insertion sort, the worst case happens because the array is large."

Recall Solution

False. The worst case is measured at a fixed size ; you vary the arrangement, not the size. Insertion sort's worst case is a reverse-sorted array of that size . Size and case are independent axes.

L1.3

Linear search scans left to right and stops at the first match. Match each situation to a case: (a) key sits at a[0], (b) key is absent, (c) key equally likely at any index.

Recall Solution
  • (a) match at the very first slot → stops after 1 comparison → best case.
  • (b) absent → must scan all slots → worst case.
  • (c) uniform over positions → take the expected cost → average case.
Figure — Best, worst, average case — with examples

Level 2 — Application

L2.1

Linear search over elements, successful search, key equally likely at each index. Give best, worst, and average comparison counts.

Recall Solution
  • Best: match at index 0 → .
  • Worst: match at index 9 (last slot) → .
  • Average: cost at index is , each with probability . Using the Gauss sum : So .

L2.2

Insertion sort comparison count on a reverse-sorted array of size . How many comparisons?

Recall Solution

Reverse-sorted is the worst case: each new key sinks all the way to the front. Outer iteration (for ) does comparisons:

L2.3

Insertion sort on an already-sorted array of size . How many comparisons?

Recall Solution

Sorted is the best case: the while test a[j] > key fails immediately every time, so each of the outer iterations does exactly 1 comparison:


Level 3 — Analysis

L3.1

Explain why insertion sort's best case () and worst case () differ by a whole order of growth, referring to what the inner loop does. Use the figure below.

Figure — Best, worst, average case — with examples

How to read the figure. The horizontal axis is the outer step (which element we are inserting); the vertical axis is the number of comparisons the inner while-loop performs on that step. The blue line is a sorted input — it stays flat at 1 comparison per step. The pink line is a reverse-sorted input — it climbs one comparison higher each step. The yellow shaded gap between them is the extra work the worst case pays; notice it widens as grows, which is the visual signature of pulling away from .

Recall Solution

The inner while loop's length is decided by how far the new key must sink to reach its sorted position.

  • Sorted input (blue path, figure): each new element is already everything before it, so the loop condition is false on its first test. That's 1 comparison per outer step → total → linear, .
  • Reverse input (pink path): each new element is smaller than everything before it, so the loop walks the entire prefix — comparisons on step . Summing → quadratic, .

The difference is how much of the prefix the inner loop traverses: a constant amount vs a growing amount. That growing-vs-constant is exactly the -vs- gap — and it is the widening yellow band in the figure.

L3.2

For linear search on a successful search with uniform key position, the average is . Show this equals here — and explain why that coincidence does not hold in general.

Recall Solution

Best , worst , so their midpoint is — which matches the average. Why it coincides here: the cost is a straight line in the index , and the index is uniformly distributed. The mean of a linear function under a uniform, symmetric distribution lands exactly at the midpoint. Why it fails in general: the average is , weighting each cost by how often it occurs. When extreme inputs are rare, they barely move the average. Quicksort is the poster child: best , worst , but the layouts are so rare that the average stays — nowhere near the midpoint.

L3.3

Consider linear search where the key is absent with probability , and if present it is uniform over the positions (present with probability ). Write the average comparison count .

Recall Solution

Split by the two disjoint events, then use :

  • Absent (prob ): scan all slots → cost .
  • Present (prob ): expected cost is the earlier .

Sanity checks: gives (always absent → always full scan); gives (matches the successful-search result). Both extremes behave correctly.


Level 4 — Synthesis

L4.1

Derive insertion sort's average comparison count. State your modeling assumption first. Give the closed form and its class.

Recall Solution

Modeling assumption (declared): the input is a uniformly random permutation of distinct values — every ordering equally likely. Under this model, when we insert element into the already-sorted prefix of length , its correct rank is uniform over the possible slots, so it displaces, on average, about half of the prefix. That justifies "sinks halfway," costing comparisons.

Sum over the outer loop : The leading term is , so — same order as the worst case, but with a constant factor of roughly half. That halved constant is exactly why insertion sort beats its worst case by a factor of 2 on typical data, yet still cannot escape . See Insertion Sort.

L4.2

A "sentinel" linear search places a copy of the key in an extra slot at the end (a[n] = x), so the scan is guaranteed to stop and never runs off the array. Suppose the key is always present in the real data a[0..n-1], uniformly at one of the real positions. Count the average key-equality comparisons a[i] == x, and separately state what the sentinel saves.

Recall Solution

Fix one cost model at a time.

Model A — count only key-equality comparisons a[i] == x. Because the key is genuinely present at some uniform real index , the loop stops at that real slot after equality comparisons; the sentinel copy is never reached. So this count is identical to plain linear search: For this is , matching L2.1. The sentinel changes this count by zero.

Model B — count the loop-control bound checks i < n (a different operation). Plain search evaluates this bound test once per iteration. The sentinel version removes it entirely: the loop is guaranteed to terminate on a match, so no i < n guard is needed each pass. This is the only thing the sentinel saves — one bound test per iteration, i.e. a per-iteration constant.

Bottom line: the sentinel leaves the equality-comparison count (, class ) untouched and trims a different operation (the bound check). Same class either way.

(If the key could be absent, the scan would reach the sentinel copy at index and stop there, costing equality comparisons for that absent event — weighted by the absence probability, as in L3.3.)

L4.3

Build a tiny distribution where average (best+worst)/2. Suppose an algorithm on size costs operation with probability and operations with probability . Compute the average for and compare to the midpoint. (Illustrated below.)

Figure — Best, worst, average case — with examples
Recall Solution

Best , worst , midpoint . Average: The average is far below the midpoint , because the expensive input is rare (only ). In the figure, the tall pink bar (cost ) is thin (weight ); its contribution to the mean is just its height times its width, so the yellow "mean" line sits low, near the fat cheap bar. This concretely disproves "average = (best+worst)/2".


Level 5 — Mastery

L5.1

Quicksort intuition. Best case is , worst is , average is . Explain, without full proof, why the average sticks near the best and not the midpoint — and why randomizing the pivot matters.

Recall Solution

Quicksort's cost is driven by how balanced each partition is. A balanced split (pivot near the median) gives recursion depth with work per level → . The worst case needs consistently terrible pivots (e.g. always the min/max), which for random data is astronomically unlikely. Averaging over all input orders, most partitions are "good enough", so the expected depth stays → average . Randomizing the pivot (Quicksort) makes the algorithm — not the input — supply the randomness, so no fixed adversarial input can force the case reliably. The average is therefore governed by the common balanced splits, landing near the best, not the midpoint.

L5.2

Distinguish average-case analysis (this chapter) from Amortized Analysis. Give one scenario where each is the right tool.

Recall Solution
  • Average-case averages over the space of inputs under a probability distribution: "for a random array, how long does linear search take?" It answers questions about typical inputs.
  • Amortized averages the cost of a sequence of operations on one data structure, with no probability — it's a worst-case guarantee spread over the sequence. Example: a dynamic array's push is amortized because the rare resize is paid for by many cheap pushes.

Right tool: use average-case when inputs are drawn randomly and you want the expected time; use amortized when a single expensive step is provably rare within a guaranteed sequence, regardless of input randomness.

L5.3

Design/refute. A student claims: "If best, worst, and average are all for an algorithm, then for every input of size ." Give an explicit algorithm that refutes this, or prove it.

Recall Solution

Refuted by an explicit algorithm. Consider count_zeros(a[0..n-1]):

c = 0
for i in 0..n-1:          # always n loop iterations
    if a[i] == 0:         # 1 comparison each iteration
        c = c + 1         # extra op only when a[i] == 0
return c

Count the basic operations (comparison, plus the increment when a zero is found):

  • The loop always does exactly comparisons, regardless of contents.
  • It does an extra increment for each zero. Let = number of zeros in the input, .

So . Now check the three cases at fixed size :

  • Best: no zeros () → , so .
  • Worst: all zeros () → , so .
  • Average: if each slot is zero with probability , expected zeros .

All three cases are , yet ranges over across inputs — it is not the single value . This refutes the claim: pins the order of growth, never the exact per-input count.


Recall One-line self-check before you leave

Best is min, Worst is max, Average is the probability-weighted mean — all at the same , and all reported in the bound language of Asymptotic Notation (Big-O, Omega, Theta).