An algorithm is a finite set of instructions to solve a specific problem. Good algorithms are efficient and correct.
Key Concepts
- Time Complexity — how runtime grows
- Space Complexity — how memory grows
- Big O Notation — O(1), O(log n), O(n), O(n²)
An algorithm is a finite set of instructions to solve a specific problem. Good algorithms are efficient and correct.
# Big O Examples O(1) - Constant: array access O(log n)- Logarithmic: binary search O(n) - Linear: simple search O(n log n)- Linearithmic: MergeSort O(n²) - Quadratic: bubble sort
# Linear Search O(n) def linear_search(arr, target): for i, val in enumerate(arr): if val == target: return i return -1 # Binary Search O(log n) def binary_search(arr, target): low, high = 0, len(arr) - 1 while low <= high: mid = (low + high) // 2 if arr[mid] == target: return mid elif arr[mid] < target: low = mid + 1 else: high = mid - 1 return -1 data = [2, 5, 8, 12, 16, 23, 38, 56] print(f"Linear: found at {linear_search(data, 23)}") print(f"Binary: found at {binary_search(data, 23)}")
What is the time complexity of binary search?
O(log n) — the search space is halved each step.
Which notation describes best-case performance?
Big Omega (Ω) describes the lower bound (best case).
Time complexity measures how an algorithm's runtime grows with input size. It helps us choose efficient algorithms for large datasets.