Optimized Binary Search¶
Two versions:
- Iterative: Generally preferred in Python for avoiding recursion overhead and stack limits. It is slightly more memory efficient.
- Recursive: Cleaner conceptually, but uses \(O(\log n)\) stack space.
Optimizations Applied:¶
- Iterative Approach: Avoids function call overhead.
- Floor Division (
//): Used for index calculation to ensure integer results. - Early Exit: Handles edge cases like empty lists or single-element lists quickly.
- No Slicing: Avoids creating new sub-lists during recursion (if using recursive approach) by passing
leftandrightindices instead. This keeps time complexity at \(O(\log n)\) and space complexity at \(O(1)\) for the iterative version.
Code (binary_search.py)¶
Which one to use?¶
- Use
binary_search_iterativefor production code in Python. It is faster and doesn't risk hitting the recursion limit for very large lists. - Use
binary_search_recursiveif you prefer code readability and don't expect extremely large inputs.
Both have \(O(\log n)\) time complexity and \(O(1)\) space complexity (for iterative) or \(O(\log n)\) space complexity (for recursive due to call stack).
In Python, mid = (left + right) // 2 will not cause an overflow.
Why?¶
Python integers have arbitrary precision. This means they can grow as large as your computer's memory allows. There is no fixed bit-width (like 32-bit or 64-bit) that truncates values. So, left + right will simply result in a larger Python integer without overflowing.
Why do people say it causes overflow?¶
This warning is critical in languages like C, C++, Java, or Go, where integers have fixed sizes (e.g., 32-bit signed integers max out at 2,147,483,647).
If left and right are both large (e.g., near 2^31 - 1), their sum can exceed the maximum value an int can hold, causing integer overflow (wrapping around to negative numbers), which breaks the binary search logic.
Safe Calculation (Language-Agnostic Best Practice)¶
To be safe across all languages and follow best practices, you can calculate mid without adding the two large numbers directly:
This avoids the intermediate sum left + right becoming larger than necessary. In Python, this isn't strictly necessary for correctness, but it's good practice if you ever translate this code to another language.
Summary for Python:¶
mid = (left + right) // 2is safe in Python.- In other languages, use
mid = left + (right - left) // 2to prevent overflow.