About

Analysis Framework & Asymptotic Notations

Analysis of Algorithm Efficiency and Asymptotic Notations

Algorithm analysis investigates how resource consumption—primarily running time and memory space—scales as the input size nn grows.

The Analysis Framework

  1. Input Size Metric (nn): The parameter measuring instance size (e.g., number of array items nn, matrix dimension n×nn \times n, or number of bits b≈⌊log⁡2n⌋+1b \approx \lfloor \log_2 n \rfloor + 1).
  2. Basic Operation: The operation contributing the most to the total running time, typically the innermost operation inside the deepest loop (e.g., key comparison, arithmetic multiplication).
  3. Execution Time Model:
T(n)≈cop⋅C(n)T(n) \approx c_{op} \cdot C(n)

where copc_{op} is the hardware/execution cost of one basic operation, and C(n)C(n) is the total count of basic operations executed. 4. Best, Worst, and Average Cases:


Asymptotic Notations (O,Ω,ΘO, \Omega, \Theta)

Asymptotic notation abstracts away machine constants and low-order terms, categorizing functions by their order of growth.

Diagram loads as you scroll.

Formal Definitions

  1. O(g(n))O(g(n)) (Asymptotic Upper Bound): t(n)∈O(g(n))t(n) \in O(g(n)) if there exist positive constants c>0c > 0 and n0≥1n_0 \ge 1 such that:

    t(n)≤c⋅g(n)for all n≥n0t(n) \le c \cdot g(n) \quad \text{for all } n \ge n_0
  2. Ω(g(n))\Omega(g(n)) (Asymptotic Lower Bound): t(n)∈Ω(g(n))t(n) \in \Omega(g(n)) if there exist positive constants c>0c > 0 and n0≥1n_0 \ge 1 such that:

    t(n)≥c⋅g(n)for all n≥n0t(n) \ge c \cdot g(n) \quad \text{for all } n \ge n_0
  3. Θ(g(n))\Theta(g(n)) (Asymptotically Tight Bound): t(n)∈Θ(g(n))t(n) \in \Theta(g(n)) if there exist positive constants c1,c2>0c_1, c_2 > 0 and n0≥1n_0 \ge 1 such that:

    c1⋅g(n)≤t(n)≤c2⋅g(n)for all n≥n0c_1 \cdot g(n) \le t(n) \le c_2 \cdot g(n) \quad \text{for all } n \ge n_0

    Equivalently: t(n)∈Θ(g(n))  ⟺  t(n)∈O(g(n)) and t(n)∈Ω(g(n))t(n) \in \Theta(g(n)) \iff t(n) \in O(g(n)) \text{ and } t(n) \in \Omega(g(n)).

Limit Quotient Method

To compare orders of growth for t(n)t(n) and g(n)g(n):

L=lim⁡n→∞t(n)g(n)L = \lim_{n \to \infty} \frac{t(n)}{g(n)}

Useful tools: L’Hôpital’s Rule lim⁡f(n)g(n)=lim⁡f′(n)g′(n)\lim \frac{f(n)}{g(n)} = \lim \frac{f'(n)}{g'(n)} and Stirling’s formula n!≈2πn(ne)nn! \approx \sqrt{2\pi n} \left(\frac{n}{e}\right)^n.


Standard Efficiency Classes

c<log⁡log⁡n<log⁡n<nc (0<c<1)<n<nlog⁡n<n2<n3<2n<n!<nnc < \log \log n < \log n < n^c \ (0 < c < 1) < n < n \log n < n^2 < n^3 < 2^n < n! < n^n

Loop Complexity Analysis Patterns

The following patterns represent the classic loop structures tested in algorithm examinations:

Pattern 1: Dependent Nested Loop

for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= i; j++)
        sum++;
}

Analysis:

∑i=1n∑j=1i1=∑i=1ni=n(n+1)2=Θ(n2)\sum_{i=1}^n \sum_{j=1}^i 1 = \sum_{i=1}^n i = \frac{n(n+1)}{2} = \Theta(n^2)

Pattern 2: Stepped Nested Loop

for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j += 4) {
        for (int k = j + 1; k < n; k++)
            count++;
    }
}

Analysis:

Total=Θ(n×n×n)=Θ(n3)\text{Total} = \Theta(n \times n \times n) = \Theta(n^3)

Pattern 3: Quadratic Loop Bound

for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n * n; j++)
        count++;
}

Analysis: The inner loop upper bound is n2n^2. For each of the nn iterations of ii, the inner loop executes ≈n2\approx n^2 times:

∑i=0n−1(n2−i−1)≈n⋅n2=Θ(n3)\sum_{i=0}^{n-1} (n^2 - i - 1) \approx n \cdot n^2 = \Theta(n^3)

Pattern 4: Repeated Squaring (j=j×jj = j \times j) vs Logarithmic Loops

for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) count++;
    for (int k = 0; k < n; k++) {
        for (int j = 2; j <= n; j = j * j)
            count++;
    }
    for (int m = 0; m < n; m++) count++;
}

Analysis:

  1. Sequence of values for jj: 2,22=4,(22)2=16,22t≤n  ⟹  2t≤log⁡2n  ⟹  t≤log⁡2(log⁡2n)2, 2^2=4, (2^2)^2=16, 2^{2^t} \le n \implies 2^t \le \log_2 n \implies t \le \log_2(\log_2 n). Hence, for (j = 2; j <= n; j = j * j) executes Θ(log⁡log⁡n)\Theta(\log \log n) times.
  2. Inside loop ii, the operations are sequential:
    • First loop: Θ(n)\Theta(n)
    • Second nested loop: n×Θ(log⁡log⁡n)=Θ(nlog⁡log⁡n)n \times \Theta(\log \log n) = \Theta(n \log \log n)
    • Third loop: Θ(n)\Theta(n)
  3. Sum per outer iteration = Θ(nlog⁡log⁡n)\Theta(n \log \log n). With nn outer iterations:
Total=n⋅Θ(nlog⁡log⁡n)=Θ(n2log⁡log⁡n)\text{Total} = n \cdot \Theta(n \log \log n) = \Theta(n^2 \log \log n)

(Note: If the inner step was multiplicative j *= 5, it would be Θ(log⁡5n)\Theta(\log_5 n), yielding Θ(n2log⁡n)\Theta(n^2 \log n)).

Pattern 5: Division Step (j=j/2j = j / 2)

for (int i = 1; i <= n; i++) {
    for (int j = n; j >= 1; j = j / 2)
        sum++;
}

Analysis: Values of jj: n,n/2,n/4,…,1n, n/2, n/4, \dots, 1. The number of halving steps until ≤1\le 1 is ⌊log⁡2n⌋+1=Θ(log⁡n)\lfloor \log_2 n \rfloor + 1 = \Theta(\log n).

Total=∑i=1nΘ(log⁡n)=Θ(nlog⁡n)\text{Total} = \sum_{i=1}^n \Theta(\log n) = \Theta(n \log n)

Pattern 6: Branching Inside Loop

for (int i = 0; i < n; i++) {
    if (i < sqrt(n)) {
        for (int j = 0; j < n; j++) count++;
    } else {
        for (int k = 0; k < n; k++) count++;
    }
}

Analysis: Regardless of whether i<ni < \sqrt{n} (true for n\sqrt{n} iterations) or i≥ni \ge \sqrt{n} (true for n−nn - \sqrt{n} iterations), exactly one branch is taken, and both branches execute exactly nn operations:

Work per outer iteration=Θ(n)  ⟹  Total=n×Θ(n)=Θ(n2)\text{Work per outer iteration} = \Theta(n) \implies \text{Total} = n \times \Theta(n) = \Theta(n^2)

Exercises

Exercise 1

Determine whether 2n+1∈O(2n)2^{n+1} \in O(2^n) and whether 22n∈O(2n)2^{2n} \in O(2^n). Justify using limits.

Show solution ↓
Solution

Part 1:

lim⁡n→∞2n+12n=lim⁡n→∞2⋅2n2n=2\lim_{n \to \infty} \frac{2^{n+1}}{2^n} = \lim_{n \to \infty} \frac{2 \cdot 2^n}{2^n} = 2

Since the limit is a finite positive constant (L=2L = 2), 2n+1∈Θ(2n)⊆O(2n)2^{n+1} \in \Theta(2^n) \subseteq O(2^n) (True).

Part 2:

lim⁡n→∞22n2n=lim⁡n→∞(2n)22n=lim⁡n→∞2n=∞\lim_{n \to \infty} \frac{2^{2n}}{2^n} = \lim_{n \to \infty} \frac{(2^n)^2}{2^n} = \lim_{n \to \infty} 2^n = \infty

Since the limit is ∞\infty, 22n∉O(2n)2^{2n} \notin O(2^n); rather, 22n∈Ω(2n)2^{2n} \in \Omega(2^n) (False).

Exercise 2

Prove that ln⁡n∈O(np)\ln n \in O(n^p) for any real constant p>0p > 0.

Show solution ↓
Solution

Using L’Hôpital’s Rule:

lim⁡n→∞ln⁡nnp=lim⁡n→∞ddn[ln⁡n]ddn[np]=lim⁡n→∞1/np⋅np−1=lim⁡n→∞1p⋅np=0\lim_{n \to \infty} \frac{\ln n}{n^p} = \lim_{n \to \infty} \frac{\frac{d}{dn}[\ln n]}{\frac{d}{dn}[n^p]} = \lim_{n \to \infty} \frac{1/n}{p \cdot n^{p-1}} = \lim_{n \to \infty} \frac{1}{p \cdot n^p} = 0

Because the limit is 00, ln⁡n\ln n grows strictly slower than any positive power of nn, confirming ln⁡n∈O(np)\ln n \in O(n^p).