btvn.vn
Tìm kiếm Đăng nhập

Tìm hai biên và đếm bằng nhị phân

Lưu trên thiết bị này
Chuyên đề lựa chọn CS: Chia để trị · Chọn bài khác

Đã thấy C vẫn cần tìm về phía đầu

Với dãy không giảm, gặp A[mid]==C chưa có nghĩa mid là vị trí đầu. Tìm tiếp nửa trái; nếu nửa trái không có C thì mid mới là vị trí đầu của miền đang xét: ```python def firstInd(A, left, right, C): if left > right: return -1 mid = (left + right) // 2 if A[mid] == C: earlier = firstInd(A, left, mid - 1, C) return earlier if earlier >= 0 else mid if A[mid] < C: return firstInd(A, mid + 1, right, C) return firstInd(A, left, mid - 1, C) ``` Mỗi mức chỉ có một lời gọi nhỏ, kể cả khi có nhiều phần tử bằng C; không quét lùi qua cả vùng trùng.

Tìm về phía cuối theo cách đối xứng

```python def lastInd(A, left, right, C): if left > right: return -1 mid = (left + right) // 2 if A[mid] == C: later = lastInd(A, mid + 1, right, C) return later if later >= 0 else mid if A[mid] < C: return lastInd(A, mid + 1, right, C) return lastInd(A, left, mid - 1, C) ``` Hai hàm trả −1 nếu không có C. Nếu có, gọi trên cả dãy để nhận first,last rồi tính last−first+1. Với A=[−2,1,1,1,4,7],C=1, hai biên là 1 và 3 nên số lượng 3. Phải kiểm first≥0 trước công thức. Khi cả hai trả −1, biểu thức −1−(−1)+1 lại bằng 1, không phải số lần xuất hiện đúng. Trường hợp không có C cần trả 0 riêng.

Đối chiếu bản quét và bản hai biên

Chạy chế độ dem của tệp thực hành. Dòng “Đếm bằng hai biên” dùng firstInd/lastInd; cần khớp bản đếm tuần tự và bản tìm rồi quét. ```text python3 g11-cs-thuc-hanh-tim-kiem.py dem "-2 1 1 1 4 7" 1 python3 g11-cs-thuc-hanh-tim-kiem.py dem "-2 1 1 1 4 7" 3 ``` Lệnh đầu đếm 3, lệnh sau đếm 0. Thử toàn dãy bằng C: first=0,last=len(A)−1 và số lượng bằng len(A). Dãy rỗng có hai biên −1 và số lượng 0. Theo mô hình thao tác cơ bản, hai lần tìm biên đều có bậc O(log n); cộng hai lần vẫn là O(log n). Điều này đến từ việc tiếp tục chia đôi để tìm từng biên, không từ cách tìm một vị trí rồi quét hết các phần tử trùng.

Bài luyện

Khi A[mid]==C trong firstInd, vì sao còn tìm ở nửa trái?
Chọn một đáp án

Bài luyện

Với first=1,last=3 đều hợp lệ, số lần xuất hiện là bao nhiêu?
Chọn một đáp án

Bài luyện

firstInd và lastInd đều trả −1 vì không có C. Hàm đếm cần làm gì?
Chọn một đáp án

Bài luyện

Vì sao bản tìm hai biên vẫn có bậc O(log n) khi toàn dãy bằng C?
Chọn một đáp án

Đang học