Skip to main content
TypeScript giúp bạn kiểm tra kiểu trước khi chạy, nhưng mã được thực thi vẫn là JavaScript. Khi tối ưu một bài toán như Top K Frequent Elements, hãy ưu tiên độ phức tạp của thuật toán và đo thời gian chạy trong điều kiện phù hợp. Trang này là một danh sách tips có thể mở rộng. Mỗi tip có cùng cấu trúc: vấn đề, cách làm và giới hạn áp dụng.

Mục lục

  1. Bỏ console.log() khỏi đoạn mã cần đo
  2. Dùng bucket thay cho sắp xếp theo tần suất

1. Bỏ log khỏi đoạn mã cần đo

Vấn đề. Nếu bạn gọi console.log(bucket) trong vòng lặp hoặc ngay trước khi trả kết quả, thời gian đo sẽ bao gồm cả việc định dạng và ghi dữ liệu ra console. Với cấu trúc lớn như mảng bucket, phần việc đó có thể che khuất thời gian của thuật toán.
Cách làm. Debug bằng log khi cần, rồi bỏ log khỏi phiên bản đem benchmark hoặc submit lên NeetCode. Nếu vẫn cần chẩn đoán, đo riêng thời gian thuật toán và thời gian xuất dữ liệu. Giới hạn. Đừng xem mọi lệnh console.log() là I/O đồng bộ: với Node.js, hành vi đồng bộ hay bất đồng bộ phụ thuộc vào stream và môi trường chạy. Điều chắc chắn là log thêm công việc ngoài thuật toán vào phép đo. Xem tài liệu console của Node.js.

2. Dùng bucket cho bài toán Top K Frequent Elements

Vấn đề. Một cách giải phổ biến là đếm tần suất, rồi sắp xếp các số theo tần suất. Nếu có m số khác nhau, bước sắp xếp theo so sánh thường tốn O(m log m) thời gian. Cách làm. Với n = nums.length, tần suất của một số chỉ có thể nằm từ 1 đến n. Tạo n + 1 bucket, trong đó bucket[count] chứa các số xuất hiện count lần. Sau đó duyệt từ bucket có tần suất cao nhất và dừng khi đã lấy đủ k số.
Độ phức tạp. Với thao tác Map có chi phí trung bình hằng số, đếm mất O(n), tạo bucket mất O(n), phân nhóm và duyệt ngược cũng mất tối đa O(n). Tổng thời gian trung bình và bộ nhớ đều là O(n). Đổi lại, bạn cấp phát n + 1 mảng bucket, kể cả khi chỉ có vài tần suất được dùng. Nếu cần thứ tự ổn định giữa các số có cùng tần suất, hãy định nghĩa thêm quy tắc sắp xếp cho trường hợp bằng nhau.

Cách đánh giá một thay đổi

Đầu tiên, kiểm tra kết quả với mảng rỗng, k = 0, số âm và các số có cùng tần suất. Tiếp theo, đo trên dữ liệu gần với đầu vào thật, giữ nguyên môi trường chạy và bỏ log khỏi đoạn mã được đo. Ưu tiên thay đổi độ phức tạp trước; chỉ giữ một tối ưu ở cấp cú pháp nếu phép đo cho thấy nó giúp ích mà vẫn dễ đọc.