Skip to Content
🧮 CTDL & Giải thuật💾 Độ phức tạp bộ nhớ

Độ phức tạp bộ nhớ (Space Complexity)

Bài viết này giúp bạn hiểu cách phân tích độ phức tạp bộ nhớ thông qua các ví dụ cụ thể với phân tích từng bước.

Space Complexity là gì?

Space Complexity đo lường lượng bộ nhớ bổ sung mà thuật toán cần sử dụng, không tính input.

💡

Space Complexity chỉ tính bộ nhớ phụ trợ (auxiliary space) - bộ nhớ mà thuật toán tạo thêm, không bao gồm input!

Các mức độ phổ biến

SpaceÝ nghĩaVí dụ
O(1)Constant - cố địnhBiến đếm, swap
O(n)Linear - tỷ lệ với nTạo mảng mới kích thước n
O(n²)QuadraticMa trận 2D n×n
O(log n)LogarithmicĐệ quy chia đôi (call stack)

Ví dụ 1: O(1) Space - In-place Operations

Bài toán

Đảo ngược mảng tại chỗ (in-place).

def reverse_inplace(arr): left = 0 # 1 biến int right = len(arr) - 1 # 1 biến int while left < right: # Swap không cần biến tạm (Python) arr[left], arr[right] = arr[right], arr[left] left += 1 right -= 1 return arr

Phân tích bộ nhớ:

  • left: 4 bytes (int)
  • right: 4 bytes (int)
  • temp: 4 bytes (int)

Tổng: 12 bytes - không phụ thuộc nO(1)

💡

Dù mảng có 10 hay 10 triệu phần tử, ta vẫn chỉ dùng 3 biến!


Ví dụ 2: O(n) Space - Tạo mảng mới

Bài toán

Đảo ngược mảng bằng cách tạo mảng mới.

def reverse_copy(arr): n = len(arr) result = [] # Mảng mới rỗng for i in range(n - 1, -1, -1): result.append(arr[i]) # Thêm n phần tử return result # result chứa n phần tử → O(n) space

Phân tích bộ nhớ:

  • n: 4 bytes (int)
  • result: n × 4 bytes (n số int)
  • i: 4 bytes (int)

Tổng: 4 + 4n + 4 = 4n + 8 bytes → O(n)


Ví dụ 3: So sánh O(1) vs O(n)

Bài toán

Tìm tất cả các cặp có tổng bằng target.

Cách 1: Brute Force - O(1) Space

def find_pairs_brute(arr, target): pairs = [] # Chỉ lưu kết quả n = len(arr) for i in range(n): # Không tạo cấu trúc phụ for j in range(i + 1, n): if arr[i] + arr[j] == target: pairs.append((arr[i], arr[j])) return pairs # Space phụ trợ: O(1) (không tính output)

Phân tích:

  • Chỉ dùng biến i, j, n
  • Không tạo cấu trúc dữ liệu phụ

Time: O(n²) | Space: O(1)

Cách 2: Hash Set - O(n) Space

def find_pairs_hash(arr, target): pairs = [] seen = set() # Set chứa tối đa n phần tử for num in arr: complement = target - num if complement in seen: pairs.append((complement, num)) seen.add(num) # Mỗi phần tử thêm 1 lần return pairs # Space phụ trợ: O(n) cho seen

Phân tích:

  • seen: chứa tối đa n phần tử
  • Mỗi phần tử: ~4-8 bytes

Time: O(n) | Space: O(n)

⚠️

Space-Time Tradeoff: Cách 2 nhanh hơn (O(n) vs O(n²)) nhưng tốn thêm O(n) bộ nhớ!


Ví dụ 4: O(log n) Space - Đệ quy

Bài toán

Binary Search với đệ quy.

def binary_search_recursive(arr, target, left, right): # Mỗi lần gọi đệ quy = 1 frame trên call stack if left > right: return -1 mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: return binary_search_recursive(arr, target, mid + 1, right) else: return binary_search_recursive(arr, target, left, mid - 1) # Gọi: binary_search_recursive(arr, target, 0, len(arr) - 1)

Phân tích Call Stack:

Lần gọiKích thước vùng tìmStack frames
1n1
2n/22
3n/43
kn/2^(k-1)k

Dừng khi: n/2^(k-1) = 1 → k = log₂n

Space: O(log n) cho call stack

💡

Đệ quy luôn tốn thêm bộ nhớ cho call stack! Binary Search iterative chỉ cần O(1) space.


Ví dụ 5: O(n) Space - Đệ quy tuyến tính

Bài toán

Tính giai thừa bằng đệ quy.

def factorial(n): if n <= 1: return 1 return n * factorial(n - 1) # factorial(5) # Call stack: # factorial(5) đang chờ # factorial(4) đang chờ # factorial(3) đang chờ # factorial(2) đang chờ # factorial(1) = 1 ← trả về

Phân tích Call Stack:

  • factorial(n) gọi factorial(n-1)
  • factorial(n-1) gọi factorial(n-2)
  • factorial(1) trả về

Số frames tối đa: n frames → O(n) space

So sánh với Iterative

def factorial_iterative(n): result = 1 # 1 biến for i in range(2, n + 1): result *= i return result # Space: O(1) - chỉ cần 2 biến

Ví dụ 6: O(n²) Space - Ma trận 2D

Bài toán

Tạo bảng nhân n×n.

def multiplication_table(n): # Tạo ma trận n x n table = [] for i in range(1, n + 1): row = [] # n rows for j in range(1, n + 1): row.append(i * j) # n columns mỗi row table.append(row) return table # Tổng: n × n = n² phần tử → O(n²) space

Phân tích:

  • Ma trận có n rows
  • Mỗi row có n columns
  • Tổng: n × n = n² phần tử

Space: O(n²)


Bảng tóm tắt

Ví dụAuxiliary SpaceLý do
Reverse in-placeO(1)Chỉ dùng vài biến
Reverse copyO(n)Tạo mảng mới n phần tử
Two Sum (brute)O(1)Không có cấu trúc phụ
Two Sum (hash)O(n)Set chứa n phần tử
Binary Search (recursive)O(log n)Call stack log n levels
Factorial (recursive)O(n)Call stack n levels
Factorial (iterative)O(1)Chỉ biến đếm
Ma trận n×nO(n²)n² phần tử

Tips phân tích Space Complexity

📌

Checklist phân tích Space:

  1. Biến đơn (int, float, bool): O(1)
  2. Mảng/List kích thước n: O(n)
  3. Ma trận n×n: O(n²)
  4. Hash Table/Set với n keys: O(n)
  5. Đệ quy: Đếm max call stack depth

Tiếp theo: Mảng (Array)