DSA - Important Time Complexities
Asymptotic Notations in Time Complexity
Section titled “Asymptotic Notations in Time Complexity”1. Big-O Notation O(f(n))
- Worst-case time complexity.
- Upper bound: algorithm takes at most
f(n)time. - Used most commonly in contests/interviews.
- Example: Binary Search →
O(log n)
2. Omega Notation Ω(f(n))
- Best-case time complexity.
- Lower bound: algorithm takes at least
f(n)time. - Not very useful alone, because best case may be rare.
- Example: Linear Search →
Ω(1)(if element is at first position)
3. Theta Notation Θ(f(n))
- Tight bound (best and worst both are
f(n)). - Algorithm always takes exactly
f(n)time asymptotically. - Example: Merge Sort →
Θ(n log n)
Complete Recurrence Solutions
Section titled “Complete Recurrence Solutions”Part A: Decremental Recurrences
Section titled “Part A: Decremental Recurrences T(n)=a⋅T(n−b)+f(n)T(n) = a \cdot T(n-b) + f(n)T(n)=a⋅T(n−b)+f(n)”General Form
- where:
- (branching factor)
- (constant decrement)
- is the non-recursive cost
Solution by Unrolling
- Expand the recurrence times where :
- At base case: , so or (constant)
Case 1: (Shrinking Recursion)
- Behavior: Exponential term as
- Dominant term: The summation
- Result:
- If is non-decreasing, the largest term is :
This only work if is non-decreasing
Case 2: (Linear Accumulation)
- Behavior: No exponential growth/decay
- Recurrence becomes:
- Solution: Direct summation of all levels
- Common subcases:
| Result | Can Be Understand as T(n-b) * F(n) ⭐ | |
|---|---|---|
| (constant) | n * c => O(n) | |
n * n => O(n^2) | ||
n * n^2 => O(n^3) | ||
n * logn => O(nlogn) |
Case 3: (Exponential Growth)
- Behavior: Exponential term dominates
- Recurrence becomes:
- If is polynomial:
- The exponential term always dominates polynomial .
Note: Skipping only work if is polynomial (or smaller than exponential)
General Unrolled Formula for Decremental Recurrence
Full Formula
Case 1: (shrinking recursion)
- Exponential term: (as )
- Skip Term
Case 2: (linear accumulation)
- Exponential terms: , → no geometric growth
- Skip & Terms
Case 3: (exponential growth)
- Exponential term dominates → cannot skip anything
- Use full formula
Summary Table:
| Case | Condition | Dominant Term | Result |
|---|---|---|---|
| 1 | Summation term | if non-decreasing | |
| 2 | All terms equal weight | if constant | |
| 3 | Exponential term |
a < 1→ F(n) dominatesa = 1→ F(n) repeatsa > 1→ T(n) dominates
My Conclusion ⭐
Case 1: a < 1
- Recursive term keeps shrinking
T(n-b)becomes very smallF(n)dominates
T(n) ≈ F(n)Case 2: a = 1
- Recursive term stays same size
F(n)added again and again- Both matter, but repetition dominates
T(n) ≈ n · F(n)Case 3: a > 1 ⭐
- Recursive term grows fast
T(n-b)dominates overF(n)F(n)becomes negligible
T(n) ≈ a^(n/b) exponentialExamples
Case 1
- Example: \begin{align} a &= 0.5 < 1\ T(n) &= \sum\_{i=0}^{n-1} (0.5)^i \cdot (n-i)\ &\approx O(n) \quad \text{(geometric series with } a < 1\text{)} \end{align}
Case 2
- Example:
- Example:
- Example 3:
Case 3
- Example: \begin{align} a = 2 > 1 \quad T(n) = 2^n \cdot T(0) + \sum\_{i=0}^{n-1} 2^i \cdot (n-i) = \Theta(2^n) \quad \text{(exponential dominates)} \end{align}
- Example: \begin{align} a &= 3 > 1 \quad T(n) = 3^{n/2} \cdot c + \text{lower order terms} = \Theta(3^{n/2}) = \Theta(\sqrt{3}^n) \end{align}
- Example:
Part B: Divide-and-Conquer Recurrences — Master Theorem
Section titled “Part B: Divide-and-Conquer Recurrences — Master Theorem”General Form
Constraints:
- (number of subproblems)
- (input size reduction factor)
- asymptotically positive
Critical Parameter ⭐
- This represents the exponent of the recursive tree cost.
- Interpretation: Compare with
Case 1: is polynomially smaller than
- Condition: for some
- Result:
- Intuition: Recursive calls dominate.
Case 2: balances with
- Condition: for some
- Result:
| Subcase | Condition | Solution |
|---|---|---|
| 2a | ||
| 2b | ||
| 2c |
- Intuition: Work is evenly distributed across levels.
Case 3: is polynomially larger than
- Condition: for some
- AND regularity condition:
- Result:
| Subcase | Condition | Solution |
|---|---|---|
| 3a | where | |
| 3b |
- Intuition: Root cost dominates.
Examples
Case 1
- Example: \begin{align} a = 4, \quad b = 2, \quad f(n) = n, \quad c = log\_2(4) = 2, \quad k = 1 \end{align}
- Compare: → Case 1
- Solution:
Case 2a
- Example: \begin{align} a &= 2, \quad b = 2, \quad f(n) = n, \quad c = log\_2(2) = 1, \quad f(n) = n^1 \cdot \log^0 n \Rightarrow k = 1, P = 0 \end{align}
- Compare: → Case 2a ()
- Solution:
Case 2b
- Example: \begin{align} a &= 2, \quad b = 2, \quad f(n) = n \cdot \log^{-1} n, \quad c = \log\_2(2) = 1, \quad k = 1, \quad P = -1 \end{align}
- Compare: → Case 2b ()
- Solution:
Case 2c
- Example: \begin{align} a &= 2,\quad b = 2,\quad f(n) = n\cdot \log^{-2} n, \quad c = \log\_2(2) = 1 \quad k = 1,\quad P = -2 \end{align}
- Compare: (c = k = 1) → Case 2c ((P < -1))
- Solution:
Case 3a
- Example: ) \begin{align} a &= 2,\quad b = 2,\quad f(n) = n^2 \quad c = \log\_2(2) = 1 \quad k = 2,\quad P = 0 \end{align}
- Compare: (c = 1 < k = 2) → Case 3a ((P \ge 0))
- Solution:
Case 3b
- Example: \begin{align} a &= 2,\quad b = 2,\quad f(n) = n^2 \log n \quad c = 1 \quad k = 2,\quad P = 1 \end{align}
- Compare: (c < k) → Case 3b
- Solution:
Case 3c
- Example: \begin{align} a &= 2,\quad b = 2,\quad f(n) = n^2 \log^{-1} n \quad c = 1 \quad k = 2,\quad P = -1 \end{align}
- Compare: (c < k) → Case 3c ((P < 0))
- Solution:
Key Differences
Section titled “Key Differences”| Feature | (Decremental) | (Divide-and-Conquer) |
|---|---|---|
| Growth type | Arithmetic reduction | Geometric reduction |
| Number of levels | ||
| When | Use Master Theorem Case 2 | |
| When | exponential | Depends on vs |
| Master Theorem | Does NOT apply | Applies |
Time Complexity in Competitive Programming
Section titled “Time Complexity in Competitive Programming”Summary ⭐
- Most competitive programming platforms allow ~10^8 operations per second.
- Generally allowed time limit: 1–2 seconds.
- So, our algorithm should have ≤ 10^8 steps/operations.
(Assume 1 input = 1 operation)
- -----→ N can be very large (practically infinite)
- -----→ (extremely large, practically infinite)
- -----→
- -----→
- -----→
- -----→
- -----→
- -----→
How to Analyze Required Time Complexity for a Problem
You need to estimate what time complexity is acceptable based on the input size n. Here’s a practical guide:
Note: 1 In second ~ 10^7 to 10^8 operations in C++ (for competitive programming).
1 sec = ~10^8 operationsFor a time complexity functionCode within this limit is likely to run in timeInput Size (n) | Acceptable Time Complexity |
|---|---|
| ≤ 10 | O(n!), O(2^n) |
| ≤ 15–20 | O(2^n) or O(n * 2^n) |
| ≤ 100 | O(n^4) |
| ≤ 1,000 | O(n^3) |
| ≤ 10,000 | O(n^2) |
| ≤ 1e5 (10^5) | O(n log n) |
| ≤ 1e6 (10^6) | O(n) |
| ~1e9 (10^9) | O(log n) or O(1) |
1. Given Input Size → Find Suitable Time Complexity
- If input size is
x - Then choose a time complexity
f(n)such that:
&#xNAN;f(x) < 10^8(operations in 1 second limit)
2. Given Time Complexity → Find Maximum Input Size
- If time complexity is
f(n) - Then choose the maximum input size
xsuch that:
&#xNAN;f(x) < 10^8
Note: f(x) represents the number of operations your program performs for input size x, and it should satisfy , f(x) < 10^8 to run within 1 second (standard time limit in competitive programming).
Why 10^8 Operations Matter in Competitive Programming ?
When you write code for competitive programming, the judge gives you 1 second to run your solution for each test case. Now, a modern computer can perform around 10⁷ to 10⁸ basic C++ operations in 1 second. So you should always make sure that:
- For a given input size, your code should not do more than
10^8operations. - If it does, the program will likely TLE (Time Limit Exceeded).
- So you would need to optimise
This is why we estimate time complexity f(n) and ensure:
f(n) < 10^8
So that your code completes within the time limit.
Example:
If your algorithm is O(n^2), then n must be ≤ 10^3, because:
→ 10^3 * 10^3 = 10^6 operations (safe)
But if n = 10^5, then → 10^10 operations (TLE)
Examples of Time Complexities and Max Input Sizes
- Brute-force Search (2 nested loops)
- Time Complexity:
O(n^2) - Max
n: ~10^3 - Example: Check all pairs
(i, j)in an array
- Time Complexity:
- Triple Nested Loop
- Time Complexity:
O(n^3) - Max
n: ~100 - Example: Matrix multiplication (naive)
- Time Complexity:
- Backtracking / Subset Generation
- Time Complexity:
O(2^n) - Max
n: ~20 - Example: Generating all subsets, permutations
- Time Complexity:
- Factorial Time
- Time Complexity:
O(n!) - Max
n: ~10 - Example: Traveling Salesman Problem (TSP)
- Time Complexity:
- Sorting Algorithms (Merge Sort, Quick Sort)
- Time Complexity:
O(n log n) - Max
n: ~10^5 to 10^6 - Example:
std::sort()in C++
- Time Complexity:
- Binary Search
- Time Complexity:
O(log n) - Max
n: up to10^9 - Example: Find element in sorted array
- Time Complexity:
- Linear Search / Prefix Sum / One-pass Scan
- Time Complexity:
O(n) - Max
n: ~10^7 - Example: Finding max in array
- Time Complexity:
- Map / Set Insert-Search (Unordered)
- Time Complexity:
O(1)average - Max
n: ~10^6 - Example:
unordered_mapin C++
- Time Complexity:
- Heap / Priority Queue Operations
- Time Complexity:
O(log n) - Max
n: ~10^6 - Example: Dijkstra’s algorithm
- Time Complexity:
- Dijkstra / BFS / DFS
- Time Complexity:
O(V + E) - Max
VorE: ~10^5 - Example: Graph traversal
- Time Complexity:
- Segment Tree / BIT (Fenwick Tree)
- Time Complexity:
O(log n)per operation - Max
n: ~10^6 - Example: Range queries and updates
- Time Complexity:
- Matrix Exponentiation / Fast Power
- Time Complexity:
O(log n) - Max
n: ~10^18 - Example: Compute
a^b mod m
- Time Complexity:
- Sieve of Eratosthenes
- Time Complexity:
O(n log log n) - Max
n: ~10^7 - Example: Prime numbers up to
n
- Time Complexity:
- DP with 1D array
- Time Complexity:
O(n) - Max
n: ~10^6 - Example: Fibonacci with memoization
- Time Complexity:
- DP with 2D array
- Time Complexity:
O(n^2) - Max
n: ~1000 - Example: Longest Common Subsequence (LCS)
- Time Complexity:
- Knapsack (DP O(n*W))
- Time Complexity:
O(n * W) - Max
n*W: ~10^7 - Example: 0/1 Knapsack
- Time Complexity:
Map Time Complexity
Map :
- Implemented by self-balancing bst (like a Red-Black Tree)
- Ordered Map : The time complexity for insertion, deletion, and access is
O(log n)Unordered Map : - uses hash tables for faster lookups.
- The average time complexity for insertion, deletion, and access is
O(1), but in the worst case, it can degrade toO(n)if there are many hash collisions.