Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
236: Implementing Binary Search
I remember a junior developer on my team a few years ago who was debugging a latency spike in our ledger service. He had written a simple loop to find a specific transaction ID in a list of a few million records. It worked perfectly in staging with 1,000 records, but in production, the API response time climbed to several seconds. When I looked at the code, I saw a classic linear search: he was checking every single element from index 0 until he found a match. The problem was that the list was already sorted, but he wasn't taking advantage of it. We switched him to a binary search, and the search time dropped from milliseconds to practically instantaneous.
The Logic of Divide and Conquer
Binary search is essentially the "phone book" method of searching. If you're looking for a name starting with 'M', you don't start at page one; you open the book to the middle. If you land on 'P', you know 'M' must be in the left half, so you throw the right half away and repeat the process with the remaining pages.
In Java, we implement this using three pointers: low, high, and mid. As long as low is less than or equal to high, we calculate the middle index. If the element at mid is our target, we're done. If the target is smaller, we move the high pointer to mid - 1. If it's larger, we move the low pointer to mid + 1. This effectively cuts the search area in half with every single iteration, giving us a time complexity of O(log n).
public int binarySearch(int[] numbers, int target) {
int low = 0;
int high = numbers.length - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (numbers[mid] == target) {
return mid; // Target found!
} else if (numbers[mid] < target) {
low = mid + 1; // Target is in the right half
} else {
high = mid - 1; // Target is in the left half
}
}
return -1; // Target not found
}
Avoiding the Integer Overflow Trap
You might have noticed I wrote int mid = low + (high - low) / 2; instead of the more intuitive (low + high) / 2. In a classroom setting, both work. In a production environment with massive arrays, the second one can crash your program.
Here is why: low and high are integers. If you have a truly giant array and both low and high are very large, adding them together can exceed the maximum value of a 32-bit signed integer (2,147,483,647). This causes an integer overflow, resulting in a negative number, which then leads to an ArrayIndexOutOfBoundsException. By subtracting low from high first, we ensure the value stays within the safe range. It's a small detail, but it's the kind of thing that separates a senior engineer from a beginner.
📋 Practical Task
Implementing a Sorted Product SKU Lookup
You are building a warehouse management system where product SKUs (stored as integers) are kept in a sorted array for fast retrieval. Your task is to implement a method that finds the index of a specific SKU. If the SKU does not exist in the array, the method should return -1.
Requirements:
- Create a class
WarehouseSearchwith a methodpublic int findSku(int[] skus, int targetSku). - Implement the binary search algorithm to ensure the lookup is O(log n).
- Use the overflow-safe method for calculating the middle index.
- Test your implementation with an array like
{1001, 1005, 1010, 1020, 1050, 1100}and search for both an existing SKU (e.g., 1020) and a non-existent one (e.g., 1015).
There are no comments for now.