DDevArchive
Đăng nhập

Big O notation: đo tốc độ thuật toán như thế nào?

Hai đoạn code cùng cho kết quả đúng, nhưng một đoạn chạy 1 giây, đoạn kia chạy 10 phút. Big O giúp bạn dự đoán code nào nhanh hơn TRƯỚC KHI chạy — và đây là câu hỏi phỏng vấn kinh điển.

Big O là gì?

Big O mô tả tốc độ tăng trưởng của thời gian chạy khi dữ liệu lớn lên. Không đo “chạy bao nhiêu giây”, mà đo “khi dữ liệu gấp đôi, thời gian tăng bao nhiêu lần?”.

Big OTên gọiVí dụ100 phần tử10.000 phần tử
O(1)Hằng sốTruy cập mảng theo index1 thao tác1 thao tác
O(log n)LogaritBinary search7 thao tác14 thao tác
O(n)Tuyến tínhDuyệt mảng 1 lần100 thao tác10.000 thao tác
O(n log n)N log NMerge sort, Quick sort700 thao tác140.000 thao tác
O(n²)Bình phươngBubble sort, 2 vòng lặp lồng10.000 thao tác100.000.000 thao tác
O(2ⁿ)Fibonacci đệ quy (chưa tối ưu)Vô cùng chậm💀 Không bao giờ xong

Nhận diện Big O từ code

// File: bigo.js
// O(1) — Hằng số: không phụ thuộc kích thước mảng
function getFirst(arr) {
  return arr[0]
}

// O(n) — Tuyến tính: duyệt mảng 1 lần
function findMax(arr) {
  let max = arr[0]
  for (const num of arr) {
    if (num > max) max = num
  }
  return max
}

// O(n²) — Bình phương: 2 vòng lặp lồng nhau
function hasDuplicate(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j]) return true
    }
  }
  return false
}

// O(n) — dùng Set thay vì 2 vòng lặp → nhanh hơn!
function hasDuplicateFast(arr) {
  const seen = new Set()
  for (const num of arr) {
    if (seen.has(num)) return true
    seen.add(num)
  }
  return false
}
💡 Quy tắc nhanh

1 vòng lặp = O(n). 2 vòng lặp lồng nhau = O(n²). Chia đôi mỗi bước = O(log n). Không có vòng lặp = O(1). Big O chỉ giữ phần lớn nhất: O(n² + n) = O(n²) vì khi n lớn, n² “nuốt” n.

Binary Search: sức mạnh của O(log n)

Tìm số trong mảng đã sắp xếp: thay vì duyệt từ đầu (O(n)), chia đôi mỗi bước. Mảng 1 triệu phần tử? Chỉ cần ~20 bước thay vì 1 triệu bước.

// File: binary-search.js
// Binary Search: tìm trong mảng ĐÃ SẮP XẾP
function binarySearch(arr, target) {
  let left = 0
  let right = arr.length - 1

  while (left <= right) {
    const mid = Math.floor((left + right) / 2)

    if (arr[mid] === target) return mid      // Tìm thấy!
    if (arr[mid] < target) left = mid + 1    // Target ở nửa phải
    else right = mid - 1                     // Target ở nửa trái
  }

  return -1 // Không tìm thấy
}

const sorted = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
console.log(binarySearch(sorted, 23)) // 5 (index)

❓ Hàm có 2 vòng lặp lồng nhau, mỗi vòng chạy n lần. Big O là?

  • Giải thích Big O bằng ví dụ thực tế
  • Nhận diện O(1), O(n), O(n²), O(log n) từ code
  • Triển khai Binary Search
  • Biết vì sao O(n²) chậm hơn O(n log n) khi n lớn