Skip to Content
🧮 CTDL & Giải thuật📝 Ví dụ phân tích Big O

Ví dụ phân tích độ phức tạp thuật toán

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

Ví dụ 1: Tính tổng các số từ 1 đến n

Bài toán

Tính tổng 1 + 2 + 3 + ... + n

Cách 1: Vòng lặp

def sum_1_to_n(n): total = 0 # 1 phép gán for i in range(1, n + 1): # Lặp n lần total += i # 1 phép cộng + 1 phép gán return total # 1 phép return

Phân tích:

  • Khởi tạo total: 1 phép
  • Vòng lặp chạy n lần, mỗi lần 2 phép (cộng và gán)
  • Return: 1 phép

Tổng: 1 + 2n + 1 = 2n + 2O(n)

Cách 2: Công thức toán học

def sum_1_to_n_formula(n): return n * (n + 1) // 2 # 3 phép: nhân, cộng, chia

Phân tích:

  • Chỉ có 3 phép cố định (dù n lớn đến đâu)

Tổng: 3O(1)

💡

Cùng một bài toán nhưng thuật toán khác nhau có độ phức tạp khác nhau: O(n) vs O(1)!


Ví dụ 2: Tìm số lớn nhất trong mảng

Bài toán

Cho mảng n số nguyên, tìm số lớn nhất.

def find_max(arr): max_val = arr[0] # 1 phép for i in range(1, len(arr)): # Lặp n-1 lần if arr[i] > max_val: # 1 so sánh max_val = arr[i] # 1 gán (có thể không chạy) return max_val # 1 phép

Phân tích:

  • Khởi tạo: 1 phép
  • Vòng lặp: (n-1) lần × 1-2 phép mỗi lần
  • Return: 1 phép

Best case: Phần tử đầu là max → (n-1) so sánh, 0 gán Worst case: Mảng tăng dần → (n-1) so sánh, (n-1) gán

Tổng: ~ n phép → O(n)


Ví dụ 3: Kiểm tra số có trùng lặp

Bài toán

Cho mảng n số, kiểm tra xem có phần tử nào xuất hiện 2 lần không?

Cách 1: So sánh từng cặp (Brute Force)

def has_duplicate_slow(arr): n = len(arr) for i in range(n): # Vòng 1: n lần for j in range(i + 1, n): # Vòng 2: trung bình n/2 lần if arr[i] == arr[j]: # 1 so sánh return True return False

Phân tích:

  • i=0: so sánh n-1 lần
  • i=1: so sánh n-2 lần
  • i=n-2: so sánh 1 lần

Tổng: (n-1) + (n-2) + … + 1 = n(n-1)/2n²/2O(n²)

Cách 2: Dùng Set (Hash Table)

def has_duplicate_fast(arr): seen = set() # O(1) for num in arr: # n lần if num in seen: # O(1) trung bình return True seen.add(num) # O(1) trung bình return False

Phân tích:

  • Vòng lặp: n lần
  • Mỗi lần: O(1) cho contains và add

Tổng: n × O(1) = O(n)

⚠️

Space-time tradeoff: Cách 2 nhanh hơn O(n) nhưng cần thêm O(n) bộ nhớ cho Set!


Bài toán

Tìm vị trí của target trong mảng đã sắp xếp.

def binary_search(arr, target): left, right = 0, len(arr) - 1 # O(1) while left <= right: # Lặp bao nhiêu lần? mid = (left + right) // 2 # O(1) if arr[mid] == target: # O(1) return mid elif arr[mid] < target: # O(1) left = mid + 1 else: right = mid - 1 return -1

Phân tích số lần lặp:

Lần lặpKích thước vùng tìm kiếm
1n
2n/2
3n/4
kn/2^(k-1)

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

Tổng: O(log n)


Ví dụ 5: Nested Loops Analysis

Bài toán

Phân tích các dạng vòng lặp lồng nhau khác nhau.

Dạng 1: Hai vòng lặp độc lập

def example_1(n): for i in range(n): # n lần print(i) for j in range(n): # n lần print(j)

Phân tích: n + n = 2nO(n)

Dạng 2: Hai vòng lặp lồng nhau

def example_2(n): for i in range(n): # n lần for j in range(n): # n lần cho mỗi i print(i, j)

Phân tích: n × n = O(n²)

Dạng 3: Vòng lặp giảm dần

def example_3(n): for i in range(n): # i từ 0 đến n-1 for j in range(i, n): # j từ i đến n-1 print(i, j)

Phân tích:

  • i=0: n lần
  • i=1: n-1 lần
  • i=n-1: 1 lần

Tổng: n + (n-1) + … + 1 = n(n+1)/2O(n²)


Bảng tóm tắt

Ví dụThuật toánTimeSpace
Tổng 1-nVòng lặpO(n)O(1)
Tổng 1-nCông thứcO(1)O(1)
Tìm maxDuyệtO(n)O(1)
Kiểm tra trùngBrute forceO(n²)O(1)
Kiểm tra trùngSetO(n)O(n)
Binary SearchChia đôiO(log n)O(1)
2 vòng lặpĐộc lậpO(n)O(1)
2 vòng lặpLồng nhauO(n²)O(1)

Tiếp theo: Mảng (Array)

Last updated on