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

Tìm kiếm nhị phân đệ quy và miền rỗng

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

Bài toán nhỏ hơn là một miền chỉ số

A đã được sắp xếp không giảm. Hàm tìm giá trị K trong miền từ left tới right, gồm cả hai đầu. Nếu tìm thấy, trả một chỉ số i có A[i]==K; nếu không có, trả −1. Nếu có nhiều giá trị bằng K, thuật toán dưới đây chỉ cần trả một vị trí, không hứa là vị trí đầu tiên. Đầu tiên gọi với left=0, right=len(A)−1. Khi left>right, miền rỗng nên trả −1 trước khi đọc A[mid]. Khi còn phần tử, so sánh phần tử giữa với K để chỉ tìm tiếp một phía.

Loại phần tử giữa khi đã biết nó khác K

```python def tim_nhi_phan(A, left, right, K): if left > right: return -1 mid = (left + right) // 2 if A[mid] == K: return mid if A[mid] < K: return tim_nhi_phan( A, mid + 1, right, K) return tim_nhi_phan( A, left, mid - 1, K) ``` Nếu A[mid]<K thì cả phần bên trái và phần tử giữa không thể là kết quả; tìm tiếp từ mid+1. Nếu A[mid]>K thì tìm bên trái tới mid−1. Hai cách đều thu hẹp miền. Return ở lời gọi tiếp chuyển kết quả tìm được về nơi gọi ban đầu.

Đếm cả lời gọi đầu và khoảng rỗng

Với A=[2,5,8,11,14] và K=17, tiến trình là: | Miền [left,right] | mid | A[mid] | Tiếp theo | |---|---|---|---| | [0,4] | 2 | 8 | [3,4] | | [3,4] | 3 | 11 | [4,4] | | [4,4] | 4 | 14 | [5,4] | | [5,4] | Không tính | Không đọc | Trả−1 | Có **bốn lần vào hàm nếu tính cả lời gọi đầu và lời gọi trên miền rỗng**; có ba lời gọi tiếp từ trong thân hàm. Phải nêu rõ cách đếm trước khi so sánh số lần gọi.

Một phần tử khác với không còn phần tử

Với A rỗng, lời gọi đầu dùng left=0, right=−1. Chỉ kiểm left==right sẽ bỏ sót trường hợp này; cần kiểm miền rỗng trước khi truy cập A. Cũng có thể thiết kế một biến thể dừng riêng khi left==right, rồi giữ mid trong nhánh trái. Với biến thể ấy vẫn cần nhánh left>right để xử lí A rỗng. Không đổi tùy ý mid−1 thành mid trong chương trình đang dùng nếu chưa kiểm lại cách thu hẹp miền và cơ sở.

Bài luyện

Theo bảng A=[2,5,8,11,14], K=17, có bao nhiêu lần vào hàm nếu tính cả lời gọi đầu và lời gọi trên miền rỗng?
Chọn một đáp án

Bài luyện

Trong hàm đang dùng, A[mid]<K và A đã xếp không giảm. Miền gọi tiếp nào phù hợp?
Chọn một đáp án

Bài luyện

Tìm trên A=[] bằng lời gọi left=0, right=-1. Việc nào cần xảy ra trước khi tính A[mid]?
Chọn một đáp án

Bài luyện

A=[2,5,5,5,9] đã sắp xếp. Hàm trong bài tìm K=5 theo yêu cầu trả một chỉ số phù hợp. Kết luận nào đúng?
Chọn một đáp án

Đang học