Cập nhật hai biên thay cho lời gọi hàm
```python
def closest_loop(A, K):
left, right = 0, len(A) - 1
while left <= right:
if left == right:
return A[left]
if right - left == 1:
if abs(A[left] - K) < abs(A[right] - K):
return A[left]
return A[right]
mid = (left + right) // 2
if A[mid] == K:
return A[mid]
if K < A[mid]:
right = mid
else:
left = mid
return None
```
Vòng lặp giữ phần tử giữa và hai cơ sở một/hai phần tử như bản đệ quy. Dãy rỗng không vào vòng lặp và trả None. Cả hai bản dùng cùng quy ước cách đều chọn giá trị lớn hơn.
Đối chiếu với cách quét mọi phần tử
Bản closest_linear trong tệp mẫu xét khoảng cách của từng giá trị và giữ ứng viên tốt nhất. Khi khoảng cách bằng nhau, cũng chọn giá trị lớn hơn để đồng bộ với hai bản nhị phân.
Ví dụ [3,9],K=6 phải cho 9 ở cả ba bản. Các cách cùng tìm đúng giá trị gần nhất, nhưng nếu không thống nhất quy ước cách đều thì có thể trả hai giá trị khác nhau mà đều gần nhất theo yêu cầu chưa ràng buộc.
Với n là số phần tử, bản quét xét tới n phần tử; hai bản thu hẹp miền giảm khoảng một nửa mỗi bước và xử lí trực tiếp khi còn một/hai phần tử. Theo mô hình thao tác cơ bản của sách, các bậc tương ứng là O(n) và O(log n).
Chạy cả ba bản và đo riêng tìm kiếm
Chạy mã bằng Python3:
```text
python3 g11-cs-thiet-ke-chia-de-tri.py gan "3 9" 6
python3 g11-cs-thiet-ke-chia-de-tri.py gan "" 6
python3 g11-cs-thiet-ke-chia-de-tri.py do --repeat 5000
```
Dãy đặt trong dấu nháy kép để truyền thành một đối số. Lệnh đầu cần cho 9 ở cả ba bản; lệnh với dãy rỗng báo “không có”. Mẫu nhận số nguyên và kiểm dãy không giảm trước khi chạy các bản nhị phân.
Phép đo dùng n=10,20,50,100, cùng dãy [0,2,...,2n−2] và K=2n−3 cho cả ba bản; K cách đều hai giá trị cuối nên kết quả chung là 2n−2. Tạo dãy đặt ngoài đoạn đo. Mỗi bản chạy 5000 lần, ghi thời gian trung bình ms/lần; đầu ra có n và ba cột tuần tự/đệ quy/vòng lặp.
Chạy lại để quan sát dao động. Bậc tăng số thao tác không ấn định thứ tự nhanh/chậm của mọi mẫu nhỏ trên một máy.
Bài luyện
Bản closest_loop cập nhật nhánh phải thế nào khi K>A[mid] và miền còn hơn hai phần tử?
Có thể loại mất phần tử gần nhất là A[mid].
Đó là phía không phù hợp với K>A[mid] theo cách đang xét.
Miền cần được thu nhỏ ở mỗi bước không kết thúc.
Giữ mid làm ứng viên gần nhất rồi tiếp tục xét bên phải.
Lời giải
Khi tìm gần nhất, A[mid] vẫn có thể là đáp số dù nhỏ hơn K. Vì vậy giữ mid làm biên trái bằng left=mid, thay vì loại nó như tìm đúng K.
Bài luyện
Muốn so sánh ba bản trên trường hợp có hai giá trị cách đều K, cần thống nhất gì?
Cùng quy ước giúp đối chiếu đúng loại kết quả mong đợi.
Bài toán vẫn cần giá trị gần nhất.
Kết quả phải là giá trị có trong dữ liệu gốc.
Điều kiện dãy không giảm vẫn cần cho thu hẹp miền.
Lời giải
Hai giá trị khác nhau có thể cùng đạt khoảng cách nhỏ nhất. Bài đã chọn quy ước trả giá trị lớn hơn; ba bản cần dùng cùng quy ước đó để so kết quả nhất quán.
Bài luyện
Trong phép đo đã nêu, vì sao tạo dãy trước khi bắt đầu timer?
Các bản cần nhận cùng dữ liệu và cùng K.
Chi phí chuẩn bị không bị trộn vào thời gian một bản tìm.
Cách đặt timer không bảo đảm một thứ tự tốc độ cho mọi lần chạy.
Vẫn phải đối chiếu kết quả của cả ba.
Lời giải
Phạm vi đo là việc tìm gần nhất trên dãy đã chuẩn bị. Đặt tạo dãy ngoài timer loại chi phí chuẩn bị khỏi số đo và giữ cùng đầu vào cho cả ba bản.
Đang học