杰瑞科技汇

java binarysearch

Of course! Here is a comprehensive guide to implementing and using the binarySearch method in Java, covering the built-in Arrays utility, manual implementation, and important best practices.

java binarysearch-图1
(图片来源网络,侵删)

The Easy Way: java.util.Arrays.binarySearch()

For most use cases, you should use the built-in binary search method from the Arrays utility class. It's highly optimized, tested, and easy to use.

Key Characteristics:

  • Requirement: The input array must be sorted in ascending order before you can use binary search. If it's not, the result is undefined.
  • Return Value:
    • The index of the search key if it is found in the array.
    • (-(insertion point) - 1) if the key is not found. This is a bit tricky but very useful for inserting the element into the correct position to maintain the sorted order.

      The "insertion point" is the index where the key would be inserted to keep the array sorted.

Method Signatures:

// For searching an array of primitives (e.g., int, long, double)
public static int binarySearch(int[] a, int key)
// For searching an array of Objects (e.g., String, Integer)
public static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
// For searching an array of Objects with natural ordering
public static <T extends Comparable<? super T>> int binarySearch(T[] a, T key)

Example 1: Searching an Array of ints

import java.util.Arrays;
public class BinarySearchExample {
    public static void main(String[] args) {
        int[] numbers = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
        int keyToFind = 23;
        // The array MUST be sorted.
        Arrays.sort(numbers); // Good practice, though already sorted here.
        // Perform the search
        int index = Arrays.binarySearch(numbers, keyToFind);
        if (index >= 0) {
            System.out.println("Element " + keyToFind + " found at index: " + index);
        } else {
            System.out.println("Element " + keyToFind + " not found.");
            // Let's see what the insertion point would be
            int insertionPoint = -index - 1;
            System.out.println("It would be inserted at index: " + insertionPoint);
        }
        System.out.println("--------------------");
        // Example of an element that is NOT in the array
        int keyToFind2 = 15;
        int index2 = Arrays.binarySearch(numbers, keyToFind2);
        if (index2 >= 0) {
            System.out.println("Element " + keyToFind2 + " found at index: " + index2);
        } else {
            System.out.println("Element " + keyToFind2 + " not found.");
            int insertionPoint2 = -index2 - 1;
            System.out.println("It would be inserted at index: " + insertionPoint2);
        }
    }
}

Output:

Element 23 found at index: 5
--------------------
Element 15 not found.
It would be inserted at index: 4

Example 2: Searching an Array of Strings (Objects)

For objects, you need to ensure they are comparable or provide a Comparator.

java binarysearch-图2
(图片来源网络,侵删)
import java.util.Arrays;
public class BinarySearchStringExample {
    public static void main(String[] args) {
        String[] languages = {"Python", "Java", "C++", "JavaScript", "Go"};
        String languageToFind = "Java";
        // The array MUST be sorted. String's natural ordering is alphabetical.
        Arrays.sort(languages);
        // Perform the search using the natural ordering of String
        int index = Arrays.binarySearch(languages, languageToFind);
        if (index >= 0) {
            System.out.println("Language \"" + languageToFind + "\" found at index: " + index);
        } else {
            System.out.println("Language \"" + languageToFind + "\" not found.");
        }
        System.out.println("--------------------");
        // Example with a custom order (e.g., by length)
        String[] words = {"apple", "banana", "kiwi", "mango", "pineapple"};
        String wordToFind = "grape";
        // Sort by length using a Comparator
        Arrays.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
        System.out.println("Array sorted by length: " + Arrays.toString(words));
        // Search using the same Comparator
        int index2 = Arrays.binarySearch(words, wordToFind, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
        if (index2 >= 0) {
            System.out.println("Word \"" + wordToFind + "\" found at index: " + index2);
        } else {
            System.out.println("Word \"" + wordToFind + "\" not found.");
            int insertionPoint = -index2 - 1;
            System.out.println("It would be inserted at index: " + insertionPoint);
        }
    }
}

Output:

Language "Java" found at index: 1
--------------------
Array sorted by length: [kiwi, apple, mango, banana, pineapple]
Word "grape" not found.
It would be inserted at index: 3

The Manual Implementation (For Learning)

Understanding the algorithm is crucial. Here is a step-by-step implementation of binary search from scratch.

The Algorithm

  1. Initialize two pointers, low (starting at 0) and high (starting at array.length - 1).
  2. While low is less than or equal to high: a. Find the middle index: mid = low + (high - low) / 2. (Using this formula avoids potential integer overflow compared to (low + high) / 2). b. Compare the element at mid with the key. c. If they are equal, you've found the element! Return mid. d. If the element at mid is less than the key, the key must be in the right half. So, set low = mid + 1. e. If the element at mid is greater than the key, the key must be in the left half. So, set high = mid - 1.
  3. If the loop finishes (meaning low has become greater than high), the element is not in the array. Return the "not found" value: -(low + 1).
public class ManualBinarySearch {
    public static int binarySearch(int[] arr, int key) {
        int low = 0;
        int high = arr.length - 1;
        while (low <= high) {
            // Find the middle index
            int mid = low + (high - low) / 2;
            // Check if the key is present at mid
            if (arr[mid] == key) {
                return mid; // Key found
            }
            // If key is greater, ignore the left half
            if (arr[mid] < key) {
                low = mid + 1;
            } 
            // If key is smaller, ignore the right half
            else {
                high = mid - 1;
            }
        }
        // Key was not present in the array
        return -(low + 1); // This matches Arrays.binarySearch() convention
    }
    public static void main(String[] args) {
        int[] numbers = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
        int key = 23;
        int result = binarySearch(numbers, key);
        if (result >= 0) {
            System.out.println("Manual search: Element " + key + " found at index: " + result);
        } else {
            System.out.println("Manual search: Element " + key + " not found.");
        }
    }
}

Complexity Analysis

Aspect Complexity Explanation
Time O(log n) With each comparison, the search space is halved. For an array of 1,000,000 elements, it takes at most 20 comparisons.
Space O(1) The iterative implementation uses a constant amount of extra space for the low, high, and mid variables.

Comparison with Linear Search (O(n))

Number of Elements Linear Search (Worst Case) Binary Search (Worst Case)
100 100 comparisons 7 comparisons
1,000 1,000 comparisons 10 comparisons
1,000,000 1,000,000 comparisons 20 comparisons

As you can see, binary search is vastly more efficient for large, sorted datasets.

java binarysearch-图3
(图片来源网络,侵删)

Key Takeaways and Best Practices

  1. Sort First, Search Second: This is the most important rule. Binary search only works on sorted data. If your data isn't sorted, you must sort it first (which is an O(n log n) operation).
  2. Use the Built-in: For production code, always prefer Arrays.binarySearch(). It's a standard, well-optimized, and reliable method.
  3. Handle the "Not Found" Case Correctly: Remember that a negative return value doesn't just mean "not found." It gives you the insertion point, which is extremely useful for algorithms that need to maintain a sorted list (like in a TreeSet or when implementing your own add method).
  4. Be Mindful of Object Comparisons: When searching an array of objects, ensure the objects are Comparable or that you provide a Comparator that is consistent with the sort order of the array. A mismatch between the sort order and the search order will lead to incorrect results.
  5. Use mid = low + (high - low) / 2: While (low + high) / 2 works for small arrays, the low + (high - low) / 2 formula is a best practice that prevents potential integer overflow for very large arrays.
分享:
扫描分享到社交APP
上一篇
下一篇