Lập trình

Tìm kiếm nhị phân trong Java: Hướng dẫn chi tiết từ A đến Z

Huy Erick

Tìm kiếm nhị phân (binary search trong Java) là một thuật toán hiệu quả để tìm kiếm một phần tử trong một mảng đã được sắp xếp. Nó hoạt động bằng cách liên tục chia...

Tìm kiếm nhị phân (binary search trong Java) là một thuật toán hiệu quả để tìm kiếm một phần tử trong một mảng đã được sắp xếp. Nó hoạt động bằng cách liên tục chia đôi phần mảng có thể chứa phần tử cần tìm cho đến khi khoanh vùng vị trí xuống chỉ còn một. Bài viết này sẽ hướng dẫn bạn chi tiết về tìm kiếm nhị phân trong Java, từ lý thuyết đến thực hành, bao gồm cả cách triển khai đệ quy và lặp, cùng với các ví dụ minh họa cụ thể và dễ hiểu.

Tìm kiếm nhị phân là gì?

Tìm kiếm nhị phân là một thuật toán được sử dụng để tìm vị trí của một giá trị mục tiêu trong một mảng đã được sắp xếp. Ý tưởng cơ bản là chia mảng làm đôi, so sánh giá trị mục tiêu với phần tử ở giữa, sau đó lặp lại quá trình này trong nửa mảng phù hợp. Hình dung như việc bạn đang tìm một trang sách trong một cuốn từ điển dày cộp. Thay vì lật từng trang một, bạn sẽ mở cuốn từ điển ở giữa, xem trang đó có chứa từ bạn cần tìm không. Nếu trang đó nằm trước từ bạn cần tìm, bạn sẽ tiếp tục tìm ở nửa sau của cuốn từ điển, và ngược lại.

Tìm kiếm nhị phân trong Java: Đệ quy và lặp

Java cung cấp nhiều cách để thực hiện tìm kiếm nhị phân. Chúng ta sẽ cùng tìm hiểu cả hai phương pháp: đệ quy và lặp.

Tìm kiếm nhị phân đệ quy trong Java

Trong tìm kiếm nhị phân đệ quy, thuật toán tự gọi lại chính nó với một phần nhỏ hơn của mảng. Dưới đây là cách triển khai:

public static int recursiveBinarySearch(int[] arr, int target, int low, int high) {     if (low > high) {         return -1; // Không tìm thấy phần tử     }     int mid = (low + high) / 2;     if (arr[mid] == target) {         return mid; // Trả về vị trí của phần tử     } else if (arr[mid] > target) {         return recursiveBinarySearch(arr, target, low, mid - 1); // Tìm kiếm trong nửa bên trái     } else {         return recursiveBinarySearch(arr, target, mid + 1, high); // Tìm kiếm trong nửa bên phải     } }
Minh họa tìm kiếm nhị phân đệ quy trong Java
  • Giải thích: Hàm recursiveBinarySearch nhận một mảng, giá trị mục tiêu, và chỉ số thấp và cao làm tham số. Nếu chỉ số thấp lớn hơn chỉ số cao, phần tử không được tìm thấy và hàm trả về -1. Chỉ số giữa được tính là trung bình cộng của chỉ số thấp và cao. Nếu phần tử ở giữa bằng giá trị mục tiêu, hàm trả về chỉ số giữa. Nếu phần tử ở giữa lớn hơn giá trị mục tiêu, hàm đệ quy tìm kiếm nửa bên trái của mảng. Nếu phần tử ở giữa nhỏ hơn giá trị mục tiêu, hàm đệ quy tìm kiếm nửa bên phải của mảng.

Tìm kiếm nhị phân lặp trong Java

Phương pháp lặp tránh được chi phí của các lời gọi đệ quy và thường hiệu quả hơn về mặt không gian. Dưới đây là cách bạn có thể triển khai nó:

public static int iterativeBinarySearch(int[] arr, int target) {     int low = 0;     int high = arr.length - 1;     while (low = high) {         int mid = (low + high) / 2;         if (arr[mid] == target) {             return mid; // Trả về vị trí của phần tử         } else if (arr[mid] > target) {             high = mid - 1; // Cập nhật chỉ số cao         } else {             low = mid + 1; // Cập nhật chỉ số thấp         }     }     return -1; // Không tìm thấy phần tử }
  • Giải thích: Hàm iterativeBinarySearch khởi tạo lowhigh lần lượt là đầu và cuối của mảng. Nó đi vào một vòng lặp while tiếp tục miễn là low nhỏ hơn hoặc bằng high. Chỉ số giữa được tính trong vòng lặp. Nếu phần tử ở giữa bằng giá trị mục tiêu, hàm trả về chỉ số giữa. Nếu phần tử ở giữa lớn hơn giá trị mục tiêu, high được cập nhật thành mid - 1. Nếu phần tử ở giữa nhỏ hơn giá trị mục tiêu, low được cập nhật thành mid + 1. Nếu vòng lặp kết thúc mà không tìm thấy giá trị mục tiêu, hàm trả về -1.

Arrays.binarySearch trong Java

Java cũng cung cấp một phương thức tích hợp sẵn cho tìm kiếm nhị phân trong lớp Arrays. Đây là một ví dụ:

int[] arr = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91}; int target = 23; int index = Arrays.binarySearch(arr, target);  if (index >= 0) {     System.out.println("Phần tử " + target + " được tìm thấy tại vị trí: " + index); } else {     System.out.println("Phần tử " + target + " không được tìm thấy trong mảng."); }
  • Giải thích: Phương thức Arrays.binarySearch đơn giản hóa quá trình thực hiện tìm kiếm nhị phân. Nó nhận mảng và giá trị mục tiêu làm tham số và trả về chỉ số của giá trị mục tiêu nếu tìm thấy, hoặc một giá trị âm nếu giá trị mục tiêu không được tìm thấy.

Ông Nguyễn Văn An, giảng viên Khoa Công nghệ thông tin, Đại học Quốc gia Hà Nội, chia sẻ: "Tìm kiếm nhị phân là một thuật toán cơ bản nhưng cực kỳ mạnh mẽ. Việc nắm vững nó sẽ giúp bạn tối ưu hóa hiệu suất tìm kiếm trong nhiều ứng dụng thực tế."

Khi nào nên dùng binary search trong Java?

Tìm kiếm nhị phân thực sự tỏa sáng khi bạn cần tìm kiếm trong một mảng đã được sắp xếp. Nếu mảng chưa được sắp xếp, bạn sẽ phải sắp xếp nó trước khi áp dụng tìm kiếm nhị phân, hoặc sử dụng các phương pháp tìm kiếm khác như tìm kiếm tuyến tính.

Bà Lê Thị Mai, chuyên gia phát triển phần mềm tại FPT Software, cho biết: "Trong các bài toán phỏng vấn, tìm kiếm nhị phân xuất hiện rất thường xuyên. Nắm vững thuật toán này sẽ giúp bạn ghi điểm với nhà tuyển dụng."

Kết luận

Binary search trong Java là một thuật toán thiết yếu trong khoa học máy tính, cung cấp độ phức tạp thời gian là O(log n), khiến nó cực kỳ hiệu quả cho việc tìm kiếm trong các mảng đã được sắp xếp. Trong Java, bạn có thể triển khai tìm kiếm nhị phân bằng cả phương pháp đệ quy và lặp, hoặc sử dụng phương thức tích hợp sẵn được cung cấp bởi lớp Arrays. Bằng cách nắm vững những kỹ thuật này, bạn có thể nâng cao kỹ năng giải quyết vấn đề của mình và sẵn sàng hơn cho các cuộc phỏng vấn kỹ thuật. Cho dù bạn sử dụng tìm kiếm nhị phân đệ quy trong Java, tìm kiếm nhị phân lặp, hay phương thức tích hợp sẵn, việc hiểu các nguyên tắc cơ bản sẽ giúp bạn viết mã hiệu quả và tối ưu.

FAQ về Binary Search trong Java

  1. Binary search trong Java là gì? Đó là một thuật toán tìm kiếm hiệu quả trên mảng đã sắp xếp, hoạt động bằng cách chia đôi mảng để tìm kiếm phần tử mục tiêu.

  2. Độ phức tạp của binary search là gì? Độ phức tạp thời gian là O(log n), rất nhanh so với tìm kiếm tuyến tính O(n).

  3. Khi nào nên dùng binary search? Nên dùng khi tìm kiếm trên mảng đã sắp xếp.

  4. Sự khác nhau giữa binary search đệ quy và lặp? Đệ quy tự gọi lại hàm, trong khi lặp sử dụng vòng lặp. Lặp thường hiệu quả hơn về bộ nhớ.

  5. Làm sao để sử dụng Arrays.binarySearch trong Java? Gọi Arrays.binarySearch(mảng, giá trị_cần_tìm).

  6. Nếu mảng chưa được sắp xếp thì sao? Bạn cần sắp xếp mảng trước hoặc dùng phương pháp tìm kiếm khác.

  7. Tìm kiếm nhị phân có quan trọng trong phỏng vấn xin việc không? Rất quan trọng, nó thường xuyên xuất hiện trong các bài toán phỏng vấn kỹ thuật.

1