Các giá trị bằng nhau nằm liền nhau
Với dãy không giảm A, các phần tử bằng C nằm trong một vùng liền nhau. Ví dụ A=[−2,1,1,1,4,7],C=1 có ba phần tử ở các chỉ số 1,2,3.
Có thể quét cả dãy để đếm. Cách của nhiệm vụ này tìm một vị trí bằng C bằng chia miền, rồi quét hai phía để bao phủ vùng trùng. Khi A[mid] khác C, thứ tự dãy giúp chọn tiếp một nửa như tìm nhị phân.
Hai biến quét đứng ngoài vùng khi dừng
```python
def countNum(A, left, right, C):
if left > right:
return 0
mid = (left + right) // 2
if A[mid] == C:
start, end = mid, mid
while start >= left and A[start] == C:
start -= 1
while end <= right and A[end] == C:
end += 1
return end - start - 1
if A[mid] < C:
return countNum(A, mid + 1, right, C)
return countNum(A, left, mid - 1, C)
```
Gọi countNum(A,0,len(A)−1,C). Hai biến start/end đi quá biên vùng bằng C một vị trí. Vì vậy chỉ số đầu thật là start+1, cuối thật là end−1; số lượng bằng (end−1)−(start+1)+1=end−start−1.
Với ví dụ trên, quét từ mid=2 rồi dừng ở start=0,end=4; số lượng là 4−0−1=3. Các biến quét có thể ra −1 hoặc len(A), nhưng điều kiện biên được kiểm trước khi đọc phần tử.
Kiểm cả vùng và số lượng
Chạy mã bằng Python3 tại thư mục chứa tệp:
```text
python3 g11-cs-thuc-hanh-tim-kiem.py dem "-2 1 1 1 4 7" 1
```
Các bản đếm cần cùng cho 3. Hàm mở rộng count_region trong tệp trả (chỉ số đầu,chỉ số cuối,số lượng), nên kết quả là (1,3,3). Nếu không có C, hàm này trả (None,None,0); riêng countNum chỉ trả số đếm 0. Thử dãy rỗng, một phần tử và vùng trùng ở đầu hoặc cuối.
Bước quét vùng phụ thuộc số phần tử bằng C. Nếu toàn dãy đều bằng C, cách này có thể quét cả dãy và có bậc O(n) trong trường hợp xấu nhất. Bài tìm hai biên tiếp theo sẽ dùng lời gọi chia đôi để tránh bước quét dài này.
Bài luyện
A=[−2,1,1,1,4,7],C=1. Số lần xuất hiện cần trả là bao nhiêu?
6 là độ dài cả dãy.
Giá trị 1 ở các chỉ số 1,2,3.
1 là giá trị cần tìm, chưa phải số lần xuất hiện.
Còn thiếu một phần tử bằng 1.
Lời giải
Các phần tử A[1],A[2],A[3] đều bằng 1 và các phần tử khác không bằng 1, nên có 3 lần xuất hiện.
Bài luyện
Hai biến quét đã dừng ở start=0,end=4 như ví dụ. Số lượng được tính thế nào?
Đó là đếm cả hai biên ngoài vùng.
Không phải công thức độ dài vùng chỉ số.
start và end đang ở ngoài vùng, cần loại hai đầu ấy.
Đã đếm thừa một vị trí so với vùng 1,2,3.
Lời giải
Vùng thật từ start+1=1 tới end−1=3, gồm cả hai đầu. Số phần tử là 3−1+1=3, tương đương end−start−1.
Bài luyện
Hàm countNum([],0,−1,C) trong bài trả gì?
Đầu ra là số đếm, không phải tín hiệu chỉ số của tìm đúng.
Không có phần tử để tạo một lần xuất hiện.
Giá trị cần tìm không tự trở thành số đếm.
Miền rỗng không có lần xuất hiện nào.
Lời giải
left=0>right=−1 nên hàm gặp cơ sở và trả 0 trước khi đọc phần tử. Không có dữ liệu thì số lần xuất hiện bằng 0.
Đang học