So sánh khoảng cách tới K
Với A đã sắp xếp không giảm, cần trả một **giá trị trong A** có khoảng cách abs(A[i]−K) nhỏ nhất. Không nhất thiết có phần tử bằng K. Trong bài này, nếu hai giá trị khác nhau cùng gần K, chọn **giá trị lớn hơn**.
Ví dụ A=[2,8,14],K=9: các khoảng cách là 7,1,5 nên kết quả là giá trị 8, không phải chỉ số 1. Dãy rỗng chưa có giá trị để chọn, hàm trả None; không dùng −1 làm tín hiệu chung vì −1 có thể là một giá trị hợp lệ trong dãy.
Phần tử giữa vẫn có thể gần nhất
Ở ví dụ A=[2,8,14],K=9, phần tử giữa là 8<K. Dù không bằng K, 8 vẫn gần hơn 14. Vì vậy nhánh phải giữ đoạn [mid,right], thay vì loại mid như tìm đúng K.
Nếu K<A[mid], giữ [left,mid] theo lập luận tương tự. Khi miền còn một phần tử, trả phần tử ấy; khi còn hai, so sánh khoảng cách và chọn theo quy ước cách đều. Hai trường hợp cơ sở này giúp miền thật sự thu nhỏ.
Dừng ở một hoặc hai phần tử
```python
def valueClosest(A, left, right, K):
if left > right:
return None
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]:
return valueClosest(A, left, mid, K)
return valueClosest(A, mid, right, K)
```
Gọi với left=0,right=len(A)−1. Nhánh hai phần tử dùng <; nếu cách đều, trả phía phải, tức giá trị lớn hơn hoặc bằng trên dãy không giảm.
Nếu bỏ cơ sở hai phần tử, miền [0,1] có mid=0. Nhánh giữ [mid,right] lại tạo [0,1], nên có thể không tiến tới điểm dừng. Không đổi cơ sở hoặc hai biên tùy ý khi chuyển từ tìm đúng sang tìm gần nhất.
Bài luyện
Với A=[2,8,14],K=9, hàm tìm gần nhất trong bài trả gì?
Đây là vị trí của 8, không phải loại đầu ra đang yêu cầu.
14 cách 9 năm đơn vị, xa hơn 8.
Tìm gần nhất vẫn có kết quả khi dãy không rỗng và K vắng.
8 có khoảng cách 1 nhỏ nhất.
Lời giải
Khoảng cách tới 9 của 2,8,14 lần lượt là 7,1,5. Vì vậy trả giá trị 8; yêu cầu không trả chỉ số và cũng không đòi A chứa đúng 9.
Bài luyện
Theo quy ước của bài, A=[3,9],K=6 cần trả giá trị nào?
Hai giá trị đều cách 6 ba đơn vị, nên chọn giá trị lớn hơn.
3 cũng gần như 9 nhưng chưa theo quy ước chọn lớn hơn của bài.
6 không nằm trong A nên không được tạo làm kết quả.
Dãy không rỗng và có ứng viên.
Lời giải
abs(3−6)=abs(9−6)=3. Bài quy định khi cách đều chọn giá trị lớn hơn, nên kết quả duy nhất theo quy ước này là 9.
Bài luyện
Vì sao cần cơ sở riêng cho miền có hai phần tử khi các nhánh giữ mid?
Yêu cầu vẫn trả giá trị gần nhất.
Với [0,1], mid=0 nên nhánh phải có thể lặp lại cùng miền.
Khoảng cách có thể bằng hoặc khác nhau.
Có thể tính và so sánh hai khoảng cách.
Lời giải
Ở miền [left,left+1], mid=left. Nếu tiếp tục gọi [mid,right], miền giữ nguyên. So sánh trực tiếp hai ứng viên ở cơ sở tránh lời gọi không thu nhỏ này.
Bài luyện
Dãy A rỗng thì hàm trả None thay vì một giá trị gần K. Vì sao phù hợp?
None biểu thị không có giá trị trả về theo quy ước.
Thuật toán tìm không cần tự sửa dữ liệu đầu vào.
Yêu cầu là chọn giá trị có thật trong dãy.
Không được tạo giá trị 0 không có trong dữ liệu.
Lời giải
A=[] cho miền [0,−1]. Hàm nhận miền rỗng và trả None vì chưa có giá trị nào để chọn; không tự thêm 0 hoặc K vào dữ liệu.
Đang học