3 ways - Đếm Số 1 trong Biểu Diễn Nhị Phân

0 0 0

Người đăng: MinhDrake

Theo Viblo Asia

1. Mô Tả Vấn Đề

Cho một số nguyên không âm n, hãy tạo mảng ans có độ dài n+1 sao cho:

ans[i] = số lượng bit 1 trong biểu diễn nhị phân của số i, với 0 ≤ i ≤ n. 

2. Các Phương Pháp và Triển khai

2.1 Phương Pháp Thô (Native)

def countBits_native(self, n: int) -> List[int]: ans = [] for i in range(n+1): ans.append(bin(i).count('1')) return ans 
  • Ý tưởng: Với mỗi i, chuyển sang chuỗi nhị phân bằng bin(i) rồi đếm ký tự '1'.
  • Độ phức tạp thời gian: O(nlog⁡n) vì mỗi bin(i).count('1') tốn O(log⁡i), tổng cộng ~∑i=0 → n: O(log⁡i)= O(n \log n).
  • Độ phức tạp không gian: O(n)

2.2 Quy Hoạch Động (DP)

def countBits_dp(self, n: int) -> List[int]: ans = [0] * (n+1) for i in range(1, n+1): ans[i] = ans[i // 2] + (i % 2) return ans 
  • Ý tưởng: Đối với mỗi số i, mối quan hệ giữa i và i /2:
    • Nếu i là số chẵn khi đó i và i/2 cùng số lượng 1 trong biểu diễn nhị phân
    • Nếu i lẻ thì biểu diễn nhị phân của i và i/2 sẽ cách nhau 1 số 1 ( least significant bit)
  • Độ phức tạp thời gian: O(n), mỗi i tính trong thời gian O(1).
  • Độ phức tạp không gian: O(n)

2.3 Đệ Quy

def countBits_recursive(self, n: int) -> List[int]: ans = [0] * (n+1) def count_ones(num): if num == 0: return 0 if ans[num] != 0: return ans[num] ans[num] = count_ones(num//2) + (num & 1) return ans[num] for i in range(1, n+1): count_ones(i) return ans 
  • Ý tưởng: Sử dụng đệ quy với bộ nhớ, áp dụng cùng công thức như DP.
  • Độ phức tạp thời gian: O(n) trung bình, mỗi số chỉ tính một lần.
  • Độ phức tạp không gian: O(n+logn), trong đó O(n) cho mảng và O(log n) cho độ sâu đệ quy.
  • Lưu ý: Có overhead của đệ quy, không thực sự tối ưu bằng DP vòng lặp.

3. Tổng Kết Độ Phức Tạp

Phương pháp Thời gian Không gian
Native (bin + count) O(n log n) O(n)
DP (dich bit + cong) O(n) O(n)
Đệ quy + Memo O(n) trung bình O(n + log n) (stack)

4. Đánh Giá và Khuyến Nghị

  • Native: Dễ hiểu, nhưng chậm khi n lớn. Phù hợp kịch bản nhỏ hoặc minh họa.
  • DP: Tối ưu nhất về thời gian và không gian. Lựa chọn hàng đầu cho dữ liệu lớn.
  • Đệ quy: Minh họa công thức đệ quy rõ ràng, nhưng overhead và rủi ro tràn stack.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Hướng dẫn finetune mô hình LLM đơn giản và miễn phí với Unsloth

Chào mừng các bạn đến với bài viết hướng dẫn chi tiết cách finetune (tinh chỉnh) một mô hình ngôn ngữ lớn (LLM) một cách đơn giản và hoàn toàn miễn phí sử dụng thư viện Unsloth. Trong bài viết này, ch

0 0 5

- vừa được xem lúc

SERIES INDEX NÂNG CAO - BÀI 1: PHÂN TÍCH NHỮNG SAI LẦM PHỔ BIẾN KHI SỬ DỤNG INDEX TRONG MYSQL

Nếu anh em thấy hay thì ủng hộ tôi 1 follow + 1 upvote + 1 bookmark + 1 comment cho bài viết này tại Mayfest 2025 nhé. Còn nếu bài viết chưa hữu ích thì tôi cũng hi vọng anh em để lại những góp ý thẳn

0 0 6

- vừa được xem lúc

"Hack" Não Số Lớn Với Digit DP!

Xin chào anh em, những chiến binh thuật toán kiên cường. Phản ứng đầu tiên của nhiều anh em (có cả tôi): "Ối dào, dễ! Quất cái for từ 1 đến 101810^{18}1018 rồi check thôi!".

0 0 8

- vừa được xem lúc

So Sánh StatelessWidget và StatefulWidget & Các Widget Nâng Cao

Chào mọi người! Hôm nay chúng ta sẽ tiếp tục hành trình khám phá Flutter và đến với bài học về StatelessWidget và StatefulWidget. Trong bài này, mình sẽ giúp các bạn phân biệt sự khác nhau giữa hai lo

0 0 4

- vừa được xem lúc

React Lifecycle & Hooks Cơ Bản

React cung cấp các phương thức lifecycle và hooks để quản lý các giai đoạn khác nhau trong vòng đời của component. Việc hiểu rõ các phương thức này giúp bạn có thể tối ưu hóa ứng dụng React của mình.

0 0 5

- vừa được xem lúc

Kafka Fundamental - Bài 4: Consumers, Deserialization, Consumer Groups & Consumer Offsets

Xin chào, lại là mình - Đức Phúc, anh chàng hơn 6 năm trong nghề vẫn nghèo technical nhưng thích viết Blog để chia sẻ kiến thức bản thân học được trong quá trình “cơm áo gạo tiền” đây. Các bạn có thể

0 0 4