Recurrences

Recurrences for divide and conquer algorithms

To process n, divide n into b size sub-parts, process each sub-part recursively, combine the outputs of each sub-part.

Time to process = T

T(n) = {
    Θ(1) for base case
    aT(n/b) + divide_step(n) + combine_step(n)
}

Solving

Example: merge sort

T(n) = {
    Θ(1)             if n <= 1
    2T(n/2) + Θ(n)   otherwise
}

Use constants

T(n) = {
    C0 if          n<=1
    2T(n/2) + C1   ow
}

Expansion method:

Expand the actual value of the recursive call then simplify. Do this until you are in a loop where you can generalize to any j'th expansion

T(n) = 2T(n/2) + C
     = 2[2T(n/4) + C(n/2)] + C
     = 2^2(T(n/2^2)) + Cn + Cn
     = 2^2[2T(n/2^3) + C(n/2^2)] + 2Cn
     = 2^3(T(n/2^3)) + 2C(n/2^2) + 2Cn
     = 2^3(T(n/2^3)) + 3Cn

T(n) expanded j times = 2^j(T(n/2^j)) + jCn

If j is log2(n), you are at base case:

2^(log2(n))C + (log2(n))Cn
= Cn + Cn(log2(n))
= Θ(nlogn)

General case: master method

T(n) = {
    Θ(1) n<=1
    aT(n/b) + Θ(n^c)
}


Case 1: logb(a) > c

T(n) = Θ(n^(logb(a)))

Case 2: logb(a) = c

T(n) = Θ(n^(logb(a)))logn

Case 3: logb(a) < c

T(n) = Θ(n^c)