{
  "slug": "binary-search",
  "title": "Binary Search",
  "category": "Searching",
  "difficulty": "easy",
  "complexity": {
    "time": "O(log n)",
    "space": "O(1)"
  },
  "idea": "On a sorted array, compare the key with the middle element and throw away the half it cannot be in. Each step halves what’s left, so it finishes in log n comparisons.",
  "code": [
    "lo, hi = 0, n-1",
    "while lo <= hi:",
    "    mid = (lo + hi) / 2",
    "    if a[mid] == key: return mid",
    "    if a[mid] < key: lo = mid + 1",
    "    else: hi = mid - 1"
  ],
  "example": {
    "array": [
      2,
      5,
      8,
      12,
      16,
      23,
      38,
      56,
      72,
      91
    ],
    "target": 23
  },
  "invariant": "Each step is the real data structure at that step — the picture is a pure function of it.",
  "stepCount": 6,
  "steps": [
    {
      "i": 0,
      "op": "say",
      "caption": "Search a sorted array for 23. The whole array is in range.",
      "note": null,
      "codeLine": 1,
      "stats": null,
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null
      ],
      "markers": [],
      "regions": [
        {
          "label": "range",
          "from": 0,
          "to": 9,
          "tone": "search"
        }
      ]
    },
    {
      "i": 1,
      "op": "read",
      "caption": "Middle a[4] = 16 < 23.",
      "note": "the key must be to the right",
      "codeLine": 3,
      "stats": {
        "steps": 1
      },
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        "read",
        null,
        null,
        null,
        null,
        null
      ],
      "markers": [
        {
          "name": "lo",
          "index": 0,
          "tone": "bound"
        },
        {
          "name": "hi",
          "index": 9,
          "tone": "bound"
        },
        {
          "name": "mid",
          "index": 4,
          "tone": "compare"
        }
      ],
      "regions": [
        {
          "label": "range",
          "from": 0,
          "to": 9,
          "tone": "search"
        }
      ]
    },
    {
      "i": 2,
      "op": "say",
      "caption": "16 is too small — discard the left half. Search indices 5…9.",
      "note": null,
      "codeLine": 5,
      "stats": {
        "steps": 1
      },
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null
      ],
      "markers": [
        {
          "name": "lo",
          "index": 5,
          "tone": "bound"
        },
        {
          "name": "hi",
          "index": 9,
          "tone": "bound"
        }
      ],
      "regions": [
        {
          "label": "range",
          "from": 5,
          "to": 9,
          "tone": "search"
        }
      ]
    },
    {
      "i": 3,
      "op": "read",
      "caption": "Middle a[7] = 56 > 23.",
      "note": "the key must be to the left",
      "codeLine": 3,
      "stats": {
        "steps": 2
      },
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        "read",
        null,
        null
      ],
      "markers": [
        {
          "name": "lo",
          "index": 5,
          "tone": "bound"
        },
        {
          "name": "hi",
          "index": 9,
          "tone": "bound"
        },
        {
          "name": "mid",
          "index": 7,
          "tone": "compare"
        }
      ],
      "regions": [
        {
          "label": "range",
          "from": 5,
          "to": 9,
          "tone": "search"
        }
      ]
    },
    {
      "i": 4,
      "op": "say",
      "caption": "56 is too big — discard the right half. Search indices 5…6.",
      "note": null,
      "codeLine": 6,
      "stats": {
        "steps": 2
      },
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null,
        null
      ],
      "markers": [
        {
          "name": "lo",
          "index": 5,
          "tone": "bound"
        },
        {
          "name": "hi",
          "index": 6,
          "tone": "bound"
        }
      ],
      "regions": [
        {
          "label": "range",
          "from": 5,
          "to": 6,
          "tone": "search"
        }
      ]
    },
    {
      "i": 5,
      "op": "found",
      "caption": "Middle is index 5 = 23. That's 23 — found it.",
      "note": null,
      "codeLine": 4,
      "stats": {
        "steps": 3
      },
      "array": [
        2,
        5,
        8,
        12,
        16,
        23,
        38,
        56,
        72,
        91
      ],
      "focus": [
        null,
        null,
        null,
        null,
        null,
        "target",
        null,
        null,
        null,
        null
      ],
      "markers": [
        {
          "name": "lo",
          "index": 5,
          "tone": "bound"
        },
        {
          "name": "hi",
          "index": 6,
          "tone": "bound"
        },
        {
          "name": "mid",
          "index": 5,
          "tone": "compare"
        }
      ],
      "regions": [
        {
          "label": "range",
          "from": 5,
          "to": 6,
          "tone": "search"
        }
      ]
    }
  ]
}