N + 1 is not an error. N - 1 compares against the pivot are necessary to examine all array elements. Additional one/two compares come from pointer crossing. There are three cases:
- Pivot is the largest element:
⬅ j
⯆
┌───┬───────────────────┬─────┐
│ p │ < p │ ≤ p │
└───┴───────────────────┴─────┘
⯅
i
j points past the end of the array. When it's decremented it checks the element pointed to by i one more time. N - 1 + 1 = N compares in total.
- Pointers cross after advancing
i:
⬅ j
⯆
┌───┬─────────┬─────┬─────┬────
│ p │ │ ≤ p │ ≥ p │
└───┴─────────┴─────┴─────┴────
⯅
i ➡
j's element was previously swapped and therefore already examined by i. When i advances (from < after a simple increment or from ≤ after a swap), it examines j's element once again. Then j is decremented and it checks an element previously pointed to by i. These 2 extra compares bring the total to N - 1 + 2 = N + 1.
- Pointers cross after advancing
j:
⬅ j
⯆
┌───┬─────────┬─────┬─────┬────
│ p │ ≤ p │ ≥ p │ ≥ p │
└───┴─────────┴─────┴─────┴────
⯅
i
j is decremented at least once to check i's element. If i stopped at an element strictly greater than the pivot, j is decremented a second time.
All in all the total number of compares is either N or N + 1. If all elements are distinct, N compares happen only when the pivot is the largest element.
The average number of compares when all elements are distinct is
1 N - 1 1
─ × N + ───── (N + 1) = N + 1 - ─
N N N
1 / N correction accounts for the (C_{N - 1}, C_0) split (pivot is the largest element) and in the limit N → ∞ it can be ignored.
Actually 1 / N doesn't affect the analysis at all.
1 2 N-1
C_N = N + 1 - ─ + ─ ∑ C_i
N N i=0
After multiplying by N
N-1
N C_N = N (N + 1) - 1 + 2 ∑ C_i
i=0
and differencing
N C_N - (N - 1) C_{N - 1} = 2 N + 2 C_{N - 1}
1 / N goes away.