<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ZenubN]]></title><description><![CDATA[ZenubN]]></description><link>https://zenubnaqvi.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>ZenubN</title><link>https://zenubnaqvi.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 20 Sep 2026 12:20:12 GMT</lastBuildDate><atom:link href="https://zenubnaqvi.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Line of Code That Broke Java's Standard Library for Nine Years]]></title><description><![CDATA[Here's a question first: if I gave you a sorted list of 8 billion numbers—roughly the population of Earth—and asked you to find one specific number, how many comparisons would you need in the worst ca]]></description><link>https://zenubnaqvi.hashnode.dev/the-line-of-code-that-broke-java-s-standard-library-for-nine-years</link><guid isPermaLink="true">https://zenubnaqvi.hashnode.dev/the-line-of-code-that-broke-java-s-standard-library-for-nine-years</guid><category><![CDATA[Binary Search Algorithm]]></category><category><![CDATA[binary search]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[cpp]]></category><category><![CDATA[C++]]></category><category><![CDATA[DSA]]></category><category><![CDATA[Computer Science]]></category><category><![CDATA[computerscience]]></category><dc:creator><![CDATA[Zenub Naqvi]]></dc:creator><pubDate>Sun, 13 Sep 2026 11:57:53 GMT</pubDate><content:encoded><![CDATA[<p>Here's a question first: if I gave you a sorted list of 8 billion numbers—roughly the population of Earth—and asked you to find one specific number, how many comparisons would you need in the worst case?</p>
<p>Not millions. Not thousands. <em><strong>Thirty-three</strong></em>. (2³³ ≈ 8.59 billion — the math isn't rounded up for effect; it's exact.)</p>
<p>Now here's the part that made me respect this algorithm instead of just tolerating it as an interview topic: the standard way almost every textbook teaches you to write binary search contains a bug so subtle it sat in Java's own standard library for about nine years before anyone noticed. It was found by <em><strong>Joshua Bloch</strong></em> — the engineer who wrote much of Java's Collections framework — and it traces back even further to Jon Bentley's original binary search implementation in his 1986 book Programming Pearls, which carried the same flaw undetected for two decades.</p>
<p>If a bug like that can hide in code written by some of the most scrutinized engineers in the industry, "I already know binary search" is a more dangerous sentence than it sounds. I'm a second-year CS student, not an expert — but this is the algorithm that first made me feel like I understood why something worked instead of just memorizing that it did. I want to hand you that same feeling, bug included.</p>
<h2>First, Let's Actually Trace It</h2>
<p>Forget the theory for a second. Say we have this sorted array and we're hunting for <code>23</code> :</p>
<blockquote>
<p><code>index: 0 1 2 3 4 5 6 7</code></p>
<p><code>value: 2 5 8 12 16 23 38 45</code></p>
</blockquote>
<ul>
<li><p><code>low = 0</code> , <code>high = 7</code> → <code>mid = 3</code> → <code>arr[3] = 12</code> . That's less than 23, so 23 must live in the right half. We just eliminated indices 0–3 without ever looking at them again.</p>
</li>
<li><p><code>low = 4</code> , <code>high = 7</code> → <code>mid = 5</code> → <code>arr[5] = 23</code> . Found it. Two comparisons. Total.</p>
</li>
</ul>
<p>A linear scan would've taken up to 8 comparisons. Binary search took 2. Scale that array up to a million elements, and linear search takes up to a million comparisons — binary search still takes about 20.</p>
<h2>The Idea Underneath the Code</h2>
<p>The reason this works isn't "we check the middle." It's this: <strong>every comparison lets you discard half the remaining data with mathematical certainty, not a guess</strong>. Because the array is sorted, when<code>arr[mid] &lt; target</code>, you don't need to check anything to the left of <code>mid</code> — sorted order has already proven it's irrelevant. You're not searching faster. You're refusing to search places that logically cannot contain the answer.</p>
<p>That's the whole algorithm. Everything below is just implementation detail.</p>
<h2>The Code (C++)</h2>
<pre><code class="language-plaintext">#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;
int binarySearch(const vector&lt;int&gt;&amp; arr, int target) {
    int low = 0, high = arr.size() - 1;
while (low &lt;= high) {
        int mid = low + (high - low) / 2;   // see note below

        if (arr[mid] == target)
            return mid;
        else if (arr[mid] &lt; target)
            low = mid + 1;    // discard left half
        else
            high = mid - 1;   // discard right half
    }
    return -1;   // not found
}
int main() {
    vector&lt;int&gt; arr = {2, 5, 8, 12, 16, 23, 38, 45};
    int target = 23;

    int result = binarySearch(arr, target);
    if (result != -1)
        cout &lt;&lt; "Found at index: " &lt;&lt; result &lt;&lt; endl;
    else
        cout &lt;&lt; "Not found." &lt;&lt; endl;
 return 0;
}
</code></pre>
<p>Run it. Change <code>target</code> to something not in the array and watch it correctly return <code>-1</code>. This isn't pseudocode — it's a complete, compilable program you can paste into any C++ compiler right now.</p>
<h3>Why It's O(log n), Properly Explained</h3>
<p>Every iteration cuts the search space in half. Starting from <code>n</code> elements, after <code>k</code> iterations, you have <code>n / 2^k</code> elements left. The loop ends when that shrinks to 1, so:</p>
<blockquote>
<p><code>n / 2^k = 1 → 2^k = n → k = log₂(n)</code></p>
</blockquote>
<p>That's not hand-waving — that's the actual derivation. For <code>n = 8,000,000,000</code>, <code>log₂(n) ≈ 33</code>. That's where the number at the top of this blog came from.</p>
<p><strong>Space complexity:</strong> the iterative version above uses O(1) extra space — just a few variables. A recursive version would use O(log n) space instead, because of the call stack building up with each recursive call. Worth knowing, because interviewers <em>will</em> ask which version you wrote and why.</p>
<h3>The Bug That's Humbled Professional Engineers</h3>
<p>Look at this line again:</p>
<blockquote>
<p><code>int mid = low + (high - low) / 2;</code></p>
</blockquote>
<p>Most people first write it as <code>(low + high) / 2</code> instead. It looks identical mathematically — and it's wrong. If <code>low</code> and <code>high</code> are both large, <code>low + high</code> can exceed the maximum value an <code>int</code> can hold and <strong>overflow</strong>, silently wrapping around into a negative number, which sends <code>mid</code> somewhere nonsensical.</p>
<p>This is the exact bug Joshua Bloch wrote about in his 2006 post, "Extra, Extra – Read All About It: Nearly All Binary Searches and Mergesorts are Broken." He found it because the binary search he'd written for the JDK itself had it — and it had been quietly shipping for close to nine years before someone's program broke and the report reached him. If it can slip past that level of scrutiny for nearly a decade, it's not a "beginner mistake" — it's a reminder that simple-looking code deserves careful reading.</p>
<h3>You Probably Don't Need to Write This By Hand</h3>
<p>Here's something they don't always tell beginners: in real C++ code, you rarely hand-roll binary search. The Standard Library already has it:</p>
<pre><code class="language-plaintext">#include &lt;algorithm&gt;

bool exists = binary_search(arr.begin(), arr.end(), 23);        // true/false
auto it = lower_bound(arr.begin(), arr.end(), 23);              // first position &gt;= 23
auto it2 = upper_bound(arr.begin(), arr.end(), 23);             // first position &gt; 23
</code></pre>
<p><code>lower_bound</code> and <code>upper_bound</code> matter more than people expect — they're how you handle <strong>duplicate values</strong> in the array, which plain binary search doesn't deal with cleanly on its own. If you're prepping for interviews, know both the hand-written version <em>and</em> these — interviewers use hand-rolled to test understanding, but production code uses STL.</p>
<h3>When Binary Search Quietly Fails You</h3>
<p>It's not a universal upgrade. It breaks down when:</p>
<ul>
<li><p><strong>The data isn't sorted</strong> — and sorting it first costs O(n log n), which can erase the benefit if you're only searching once.</p>
</li>
<li><p><strong>You're working with a linked list</strong> — binary search needs random access (jumping straight to index <code>mid</code>)which arrays give you and linked lists don't.</p>
</li>
<li><p><strong>The dataset changes constantly</strong> — frequent insertions/deletions can make maintaining sorted order more expensive than the search savings.</p>
</li>
</ul>
<p>Knowing when <em>not</em> to use an algorithm is as much a sign of understanding it as knowing when to use it.</p>
<h3>Where This Idea Runs the World</h3>
<p>Once you see the pattern, it's everywhere:</p>
<ul>
<li><p><code>git bisect</code> Binary searches your commit history to find which commit introduced a bug.</p>
</li>
<li><p><strong>Database indexes</strong> (B-Trees) use the same halving principle to avoid scanning entire tables.</p>
</li>
<li><p><strong>Rate-limiting and capacity planning</strong> in systems design often use binary-search-style thinking to find a breaking point efficiently.</p>
</li>
</ul>
<p>It's less "an algorithm for arrays" and more "a strategy for eliminating half of any problem, fast."</p>
<h3>Where I'm At</h3>
<p>I'm writing this as a second-year student a few weeks into serious DSA practice — not as someone who's mastered it. But I've found that the topics I initially found hardest are the ones I can now explain most clearly, precisely because I had to slow down and actually understand them instead of pattern-matching my way through. If any part of this saved you the slow version of that process, it did its job.</p>
<p>First post in what I'm hoping becomes a habit: writing about the small ideas in computer science that turn out to be bigger than they look.</p>
]]></content:encoded></item></channel></rss>