{
  "id": "searching/ternary-search",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/searching/ternary-search",
  "topic": {
    "slug": "searching",
    "title": "Searching"
  },
  "title": "Ternary Search",
  "tagline": "Cut into thirds instead of halves — and discover it's actually slower.",
  "vizKind": "array",
  "complexity": {
    "time": {
      "best": "O(1)",
      "average": "O(log n)",
      "worst": "O(log n)"
    },
    "space": "O(1)",
    "growth": "log",
    "note": "Still logarithmic — but with a worse constant than binary search. Roughly 2·log₃(n) ≈ 1.26·log₂(n) comparisons, against binary search's 1.0. Same complexity class, measurably more work."
  },
  "code": {
    "javascript": "function ternarySearch(a, target) {\n  let lo = 0, hi = a.length - 1;\n  while (lo <= hi) {\n    const third = Math.floor((hi - lo) / 3);\n    const m1 = lo + third;\n    const m2 = hi - third;\n    if (a[m1] === target) return m1;\n    if (a[m2] === target) return m2;\n    if (target < a[m1]) hi = m1 - 1;\n    else if (target > a[m2]) lo = m2 + 1;\n    else { lo = m1 + 1; hi = m2 - 1; }\n  }\n  return -1;\n}",
    "python": "def ternary_search(a, target):\n    lo, hi = 0, len(a) - 1\n    while lo <= hi:\n        third = (hi - lo) // 3\n        m1 = lo + third\n        m2 = hi - third\n        if a[m1] == target: return m1\n        if a[m2] == target: return m2\n        if target < a[m1]: hi = m1 - 1\n        elif target > a[m2]: lo = m2 + 1\n        else: lo, hi = m1 + 1, m2 - 1\n\n    return -1\n",
    "java": "int ternarySearch(int[] a, int target) {\n  int lo = 0, hi = a.length - 1;\n  while (lo <= hi) {\n    int third = (hi - lo) / 3;\n    int m1 = lo + third;\n    int m2 = hi - third;\n    if (a[m1] == target) return m1;\n    if (a[m2] == target) return m2;\n    if (target < a[m1]) hi = m1 - 1;\n    else if (target > a[m2]) lo = m2 + 1;\n    else { lo = m1 + 1; hi = m2 - 1; }\n  }\n  return -1;\n}",
    "cpp": "int ternarySearch(vector<int> a, int target) {\n  int lo = 0, hi = a.size() - 1;\n  while (lo <= hi) {\n    int third = (hi - lo) / 3;\n    int m1 = lo + third;\n    int m2 = hi - third;\n    if (a[m1] == target) return m1;\n    if (a[m2] == target) return m2;\n    if (target < a[m1]) hi = m1 - 1;\n    else if (target > a[m2]) lo = m2 + 1;\n    else { lo = m1 + 1; hi = m2 - 1; }\n  }\n  return -1;\n}"
  },
  "defaultInput": [
    3,
    7,
    12,
    18,
    24,
    31,
    40,
    55,
    63,
    77,
    82,
    91
  ],
  "defaultTarget": 82,
  "inputHint": "Count the comparisons, then try the same list on Binary Search.",
  "pitfalls": [
    {
      "wrong": "Assuming more splits means fewer comparisons.",
      "right": "Fewer rounds, but more comparisons per round. Ternary does about 26% more work than binary search. Count comparisons, not iterations."
    },
    {
      "wrong": "Using it to search a sorted array in real code.",
      "right": "Don't — binary search is strictly better. Ternary search's real home is finding the peak of a unimodal function, where sorted order doesn't exist."
    },
    {
      "wrong": "Getting the three-way boundaries wrong.",
      "right": "The middle third is (m1, m2) exclusive — you already checked both probes. Set lo = m1 + 1 and hi = m2 − 1, or you'll re-check them forever."
    }
  ],
  "quiz": [
    {
      "q": "Ternary search does fewer rounds than binary search. Is it faster?",
      "options": [
        "Yes — fewer rounds means less work",
        "No — each round costs two comparisons instead of one, so it does more work overall",
        "They're exactly the same",
        "Yes, but only on large lists"
      ],
      "answer": 1,
      "why": "Fewer rounds, but double the comparisons per round. It works out to about 26% more comparisons than binary search — slower, despite feeling cleverer."
    },
    {
      "q": "What is ternary search genuinely good for?",
      "options": [
        "Searching a sorted array",
        "Finding the peak of a curve that rises then falls",
        "Sorting",
        "Nothing at all"
      ],
      "answer": 1,
      "why": "On a unimodal function there is no sorted order to binary-search. Comparing two probe points tells you which side the peak is on — that's a job binary search cannot do."
    },
    {
      "q": "What's the general lesson here?",
      "options": [
        "Always split into as many parts as possible",
        "An idea can feel faster and be measurably slower — count, don't guess",
        "Logarithms are always fast",
        "Binary search is the only good algorithm"
      ],
      "answer": 1,
      "why": "That's the real takeaway. Intuition proposes; the comparison count decides. Plenty of 'obvious' optimisations are slower once you actually measure them."
    }
  ],
  "problems": [
    {
      "name": "Binary Search",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/binary-search/"
    },
    {
      "name": "Peak Index in a Mountain Array",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/peak-index-in-a-mountain-array/"
    },
    {
      "name": "Find Peak Element",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/find-peak-element/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 7,
    "frames": [
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 1,
        "variables": {
          "target": 82,
          "size": 12
        },
        "explanation": "Binary search cuts the window in half. Ternary search cuts it into thirds — surely that's faster? Let's count and find out.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [
          {
            "name": "lo",
            "index": 0
          },
          {
            "name": "m1",
            "index": 3
          },
          {
            "name": "m2",
            "index": 8
          },
          {
            "name": "hi",
            "index": 11
          }
        ],
        "highlights": [
          {
            "index": 3,
            "role": "active"
          },
          {
            "index": 8,
            "role": "active"
          }
        ],
        "codeLine": 5,
        "variables": {
          "lo": 0,
          "m1": 3,
          "m2": 8,
          "hi": 11,
          "window": 12
        },
        "explanation": "Split the window into three with two probes: 18 at 3 and 63 at 8. Note that's *two* looks, not one.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 6,
            "role": "discarded"
          },
          {
            "index": 7,
            "role": "discarded"
          },
          {
            "index": 8,
            "role": "discarded"
          }
        ],
        "codeLine": 10,
        "variables": {
          "lo": 9,
          "hi": 11
        },
        "explanation": "82 is bigger than 63, so it can only be in the last third. Drop the first two.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "discarded"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [
          {
            "name": "lo",
            "index": 9
          },
          {
            "name": "m1",
            "index": 9
          },
          {
            "name": "m2",
            "index": 11
          },
          {
            "name": "hi",
            "index": 11
          }
        ],
        "highlights": [
          {
            "index": 9,
            "role": "active"
          },
          {
            "index": 11,
            "role": "active"
          },
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 6,
            "role": "discarded"
          },
          {
            "index": 7,
            "role": "discarded"
          },
          {
            "index": 8,
            "role": "discarded"
          }
        ],
        "codeLine": 5,
        "variables": {
          "lo": 9,
          "m1": 9,
          "m2": 11,
          "hi": 11,
          "window": 3
        },
        "explanation": "Split the window into three with two probes: 77 at 9 and 91 at 11. Note that's *two* looks, not one.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 6,
            "role": "discarded"
          },
          {
            "index": 7,
            "role": "discarded"
          },
          {
            "index": 8,
            "role": "discarded"
          },
          {
            "index": 9,
            "role": "discarded"
          },
          {
            "index": 11,
            "role": "discarded"
          }
        ],
        "codeLine": 11,
        "variables": {
          "lo": 10,
          "hi": 10
        },
        "explanation": "82 sits between the two probes, so it must be in the middle third.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "discarded"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [
          {
            "name": "lo",
            "index": 10
          },
          {
            "name": "m1",
            "index": 10
          },
          {
            "name": "m2",
            "index": 10
          },
          {
            "name": "hi",
            "index": 10
          }
        ],
        "highlights": [
          {
            "index": 10,
            "role": "active"
          },
          {
            "index": 10,
            "role": "active"
          },
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 6,
            "role": "discarded"
          },
          {
            "index": 7,
            "role": "discarded"
          },
          {
            "index": 8,
            "role": "discarded"
          },
          {
            "index": 9,
            "role": "discarded"
          },
          {
            "index": 11,
            "role": "discarded"
          }
        ],
        "codeLine": 5,
        "variables": {
          "lo": 10,
          "m1": 10,
          "m2": 10,
          "hi": 10,
          "window": 1
        },
        "explanation": "Split the window into three with two probes: 82 at 10 and 82 at 10. Note that's *two* looks, not one.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-7",
            "value": 7
          },
          {
            "id": "c2-12",
            "value": 12
          },
          {
            "id": "c3-18",
            "value": 18
          },
          {
            "id": "c4-24",
            "value": 24
          },
          {
            "id": "c5-31",
            "value": 31
          },
          {
            "id": "c6-40",
            "value": 40
          },
          {
            "id": "c7-55",
            "value": 55
          },
          {
            "id": "c8-63",
            "value": 63
          },
          {
            "id": "c9-77",
            "value": 77
          },
          {
            "id": "c10-82",
            "value": 82
          },
          {
            "id": "c11-91",
            "value": 91
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 10,
            "role": "found"
          },
          {
            "index": 0,
            "role": "discarded"
          },
          {
            "index": 1,
            "role": "discarded"
          },
          {
            "index": 2,
            "role": "discarded"
          },
          {
            "index": 3,
            "role": "discarded"
          },
          {
            "index": 4,
            "role": "discarded"
          },
          {
            "index": 5,
            "role": "discarded"
          },
          {
            "index": 6,
            "role": "discarded"
          },
          {
            "index": 7,
            "role": "discarded"
          },
          {
            "index": 8,
            "role": "discarded"
          },
          {
            "index": 9,
            "role": "discarded"
          },
          {
            "index": 11,
            "role": "discarded"
          }
        ],
        "codeLine": 7,
        "variables": {
          "result": 10,
          "looks": 7
        },
        "explanation": "Found 82 at index 10 after 7 comparisons.",
        "stats": {
          "comparisons": 7,
          "swaps": 0
        },
        "accent": "found"
      }
    ]
  }
}