Playground Component

Exponential Search
Visualizer

Visualize Exponential Search as it grows a search range quickly, then uses Binary Search inside that range.

Exponential Search Visualizer

Exponential Search Visualizer

Status

Idle

Bound

-

Left

-

Mid

-

Right

-

Comparisons

0

Target

-

Copy Code


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Exponential Search Visualizer</title>
  <style>
    :root{--bg:#090909;--panel:#111111;--gold:#f4c430;--gold-dark:#b88700;--text:#f5f5f5;--border:#2f2f2f}
    *{box-sizing:border-box}
    body{margin:0;background:#090909}
    .search-visualizer{min-height:100vh;padding:40px;background:radial-gradient(circle at top,#1a1505 0%,#090909 40%);color:var(--text);font-family:'Poppins',Arial,sans-serif}
    .search-visualizer h2{text-align:center;font-size:3rem;color:var(--gold);margin:0 0 35px}
    .controls{display:flex;justify-content:center;gap:15px;flex-wrap:wrap;margin-bottom:35px}
    .controls input{width:160px;padding:14px;border-radius:12px;border:1px solid #555;background:#151515;color:var(--gold);text-align:center;font-size:16px;outline:none}
    .controls input:focus{border-color:var(--gold)}
    .controls button{padding:14px 22px;border:none;border-radius:12px;cursor:pointer;font-weight:600;font-size:15px;background:linear-gradient(180deg,#ffd54d,#d9a900);color:#111;transition:.25s}
    .controls button:hover{transform:translateY(-2px)}
    .stats{width:100%;max-width:900px;margin:auto auto 40px;display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
    .stat-box{background:#151515;border:1px solid #2b2b2b;border-radius:14px;padding:18px;text-align:center}
    .stat-box h4{margin:0;color:#999;font-size:.9rem}
    .stat-box p{margin:8px 0 0;color:var(--gold);font-size:1.4rem;font-weight:bold}
    .array{display:flex;justify-content:center;flex-wrap:wrap;gap:14px}
    .cell{width:72px;height:72px;border-radius:14px;background:#171717;border:2px solid #2c2c2c;display:flex;flex-direction:column;justify-content:center;align-items:center;transition:.25s}
    .cell div{font-size:1.3rem;font-weight:700}
    .cell small{margin-top:5px;color:#999;font-size:.72rem}
    .cell.default{background:#171717}
    .cell.range{background:#241d08;border-color:#6f560f}
    .cell.checking{background:#ffb000;color:black;border-color:#ffd54d;transform:translateY(-8px) scale(1.05);box-shadow:0 0 20px rgba(255,193,7,.45)}
    .cell.found{background:#25c05a;color:white;border-color:#43e97b;transform:scale(1.12);box-shadow:0 0 22px rgba(37,192,90,.5)}
    .cell.discarded{opacity:.28}
    .cell.left{border:2px solid #4ea8ff}
    .cell.right{border:2px solid #ff6b6b}
    .cell.mid{background:#b26dff;border-color:#d7b3ff}
    .cell.bound{border:2px solid #f4c430;box-shadow:0 0 16px rgba(244,196,48,.32)}
    @media(max-width:768px){.search-visualizer{padding:20px}.search-visualizer h2{font-size:2rem}.stats{grid-template-columns:repeat(2,1fr)}.cell{width:58px;height:58px}.cell div{font-size:1rem}}
  </style>
</head>
<body>
  <div class="search-visualizer">
    <h2>Exponential Search Visualizer</h2>
    <div class="controls">
      <button id="randomizeBtn">Randomize</button>
      <input id="targetInput" type="number" placeholder="Target">
      <button id="searchBtn">Search</button>
      <button id="speedBtn">Speed: Normal</button>
    </div>
    <div class="stats">
      <div class="stat-box"><h4>Status</h4><p id="status">Idle</p></div>
      <div class="stat-box"><h4>Bound</h4><p id="bound">-</p></div>
      <div class="stat-box"><h4>Left</h4><p id="left">-</p></div>
      <div class="stat-box"><h4>Mid</h4><p id="mid">-</p></div>
      <div class="stat-box"><h4>Right</h4><p id="right">-</p></div>
      <div class="stat-box"><h4>Comparisons</h4><p id="comparisons">0</p></div>
      <div class="stat-box"><h4>Target</h4><p id="targetValue">-</p></div>
    </div>
    <div id="array" class="array"></div>
  </div>

  <script>
    const speedLevels=[{name:"Very Slow",delay:500},{name:"Slow",delay:200},{name:"Normal",delay:100},{name:"Fast",delay:50},{name:"Very Fast",delay:10}];
    let array=[],speedIndex=2,searching=false,bound=-1,left=-1,mid=-1,right=-1;
    const arrayEl=document.getElementById("array"),targetInput=document.getElementById("targetInput"),speedBtn=document.getElementById("speedBtn");
    function sleep(ms){return new Promise(resolve=>setTimeout(resolve,ms))}
    function createSortedArray(){const used=new Set(),arr=[];while(arr.length<48){const value=Math.floor(Math.random()*100)+10;if(!used.has(value)){used.add(value);arr.push({value,state:"default"})}}return arr.sort((a,b)=>a.value-b.value)}
    function setStatus(value){document.getElementById("status").textContent=value}
    function setMarker(id,value){document.getElementById(id).textContent=value===-1?"-":value}
    function setComparisons(value){document.getElementById("comparisons").textContent=value}
    function syncTarget(){document.getElementById("targetValue").textContent=targetInput.value||"-"}
    function renderArray(){
      arrayEl.innerHTML="";
      array.forEach((item,index)=>{
        const classes=["cell"];
        if(index===bound)classes.push("bound");
        if(index===left)classes.push("left");
        if(index===right)classes.push("right");
        if(index===mid)classes.push("mid");
        classes.push(item.state);
        const cell=document.createElement("div");
        cell.className=classes.join(" ");
        cell.innerHTML=`<div>${item.value}</div><small>Index ${index}</small>`;
        arrayEl.appendChild(cell);
      });
    }
    function setBound(value){bound=value;setMarker("bound",value);renderArray()}
    function setLeft(value){left=value;setMarker("left",value);renderArray()}
    function setRight(value){right=value;setMarker("right",value);renderArray()}
    function setMid(value){mid=value;setMarker("mid",value);renderArray()}
    function clearMarkers(){setBound(-1);setLeft(-1);setMid(-1);setRight(-1)}
    function setCellState(index,state){if(array[index]){array[index].state=state;renderArray()}}
    function setRangeState(start,end,state){array=array.map((item,index)=>index>=start&&index<=end?{...item,state}:item);renderArray()}
    function resetStates(){array=array.map(item=>({...item,state:"default"}));renderArray()}
    function randomize(){if(searching)return;array=createSortedArray();targetInput.value="";clearMarkers();setComparisons(0);setStatus("Idle");syncTarget();renderArray()}
    function toggleSpeed(){speedIndex=(speedIndex+1)%speedLevels.length;speedBtn.textContent=`Speed: ${speedLevels[speedIndex].name}`}
    async function exponentialSearch(){
      if(searching)return;
      const target=Number(targetInput.value);
      if(Number.isNaN(target)||targetInput.value==="")return;
      searching=true;resetStates();clearMarkers();setComparisons(0);setStatus("Expanding range...");syncTarget();
      let comps=1;setComparisons(comps);setBound(0);setCellState(0,"checking");
      await sleep(speedLevels[speedIndex].delay);
      if(array[0].value===target){setCellState(0,"found");setStatus("Found!");searching=false;return}
      setCellState(0,"discarded");
      let i=1;
      while(i<array.length&&array[i].value<=target){
        setBound(i);setCellState(i,"checking");comps++;setComparisons(comps);
        await sleep(speedLevels[speedIndex].delay);
        if(array[i].value===target){setCellState(i,"found");setStatus("Found!");searching=false;return}
        setCellState(i,"discarded");i*=2;
      }
      let l=Math.floor(i/2)+1,r=Math.min(i,array.length-1);
      setLeft(l);setRight(r);setStatus("Binary scan...");setRangeState(l,r,"range");
      await sleep(speedLevels[speedIndex].delay);
      while(l<=r){
        const m=Math.floor((l+r)/2);
        setLeft(l);setRight(r);setMid(m);setCellState(m,"checking");comps++;setComparisons(comps);
        await sleep(speedLevels[speedIndex].delay);
        if(array[m].value===target){setCellState(m,"found");setStatus("Found!");searching=false;return}
        if(array[m].value<target){setRangeState(l,m,"discarded");l=m+1}
        else{setRangeState(m,r,"discarded");r=m-1}
        await sleep(speedLevels[speedIndex].delay);
      }
      clearMarkers();setStatus("Not Found");searching=false;
    }
    document.getElementById("randomizeBtn").addEventListener("click",randomize);
    document.getElementById("searchBtn").addEventListener("click",exponentialSearch);
    speedBtn.addEventListener("click",toggleSpeed);
    targetInput.addEventListener("input",syncTarget);
    randomize();
  </script>
</body>
</html>
    

About this Component

Exponential Search is a searching algorithm for sorted data. It first checks positions that grow exponentially, such as 1, 2, 4, 8, and so on, until it finds a range where the target could be located. After that range is found, it performs Binary Search inside the bounded section. This interactive visualization helps you see the two phases clearly: the rapid range expansion phase and the focused binary search phase that follows. Exponential Search has a best-case time complexity of O(1) when the first element is the target, and an average and worst-case time complexity of O(log n). It uses O(1) extra space in an iterative implementation and is especially useful for sorted arrays when the size is unknown or when the target is likely near the beginning.

Explore More Components

Discover more components from the Playground.

Share Feedback