惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
爱范儿
爱范儿
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
Jina AI
Jina AI
B
Blog
N
Netflix TechBlog - Medium
Recent Announcements
Recent Announcements
aimingoo的专栏
aimingoo的专栏
腾讯CDC
C
Check Point Blog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - Franky
罗磊的独立博客
B
Blog RSS Feed
WordPress大学
WordPress大学
小众软件
小众软件
博客园 - 叶小钗
M
MIT News - Artificial intelligence
GbyAI
GbyAI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
The Math Behind O(log n): Binary Search, log , and Why Ha...
Anh Quân Nguyễn · 2026-06-12 · via DEV Community

You have read O(log n) a hundred times. Binary search is O(log n). A balanced BST lookup is O(log n). Heap insert is O(log n). We nod along — log n means "fast" — and move on.

But what is that logarithm actually counting? Once it clicks, a whole family of algorithms stops being trivia you memorized and becomes one idea you understand.

A logarithm counts halvings

Forget the textbook definition for a second. Here's the one that matters for algorithms:

log₂(n) is the number of times you can halve n before you reach 1.

That's it. Start with n, keep dividing by 2, count the steps:

64 → 32 → 16 → 8 → 4 → 2 → 1     = 6 steps   →  log₂(64) = 6
1000 → 500 → ... → ~1            ≈ 10 steps  →  log₂(1000) ≈ 9.97
1,000,000 → ...                 ≈ 20 steps  →  log₂(1,000,000) ≈ 19.93

The headline number every engineer should have burned into memory: log₂ of a million is about 20. A billion is about 30. The input grew by 1000×, the work grew by 10. That gap is the entire reason O(log n) feels like magic.

Binary search is just "halve until found"

Binary search is the canonical halving algorithm. Each comparison throws away half of what's left:

def binary_search(arr, target):
    lo, hi = 0, len(arr) - 1
    steps = 0
    while lo <= hi:
        steps += 1
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid, steps
        elif arr[mid] < target:
            lo = mid + 1      # discard the lower half
        else:
            hi = mid - 1      # discard the upper half
    return -1, steps

Run it on a sorted array of one million integers and steps never exceeds 20 — no matter which element you search for. A linear scan would average 500,000 comparisons. Same data, same machine, a 25,000× difference in worst-case work. The only thing that changed is that binary search halves while the scan decrements.

That's the whole trick: decrementing gives you O(n); halving gives you O(log n).

Where halving shows up once you see it

The moment you read O(log n) as "halving," you start spotting the same move everywhere:

  • Balanced trees (AVL, red-black, B-trees): each level splits the remaining keys in two, so the tree is ~log₂(n) deep. A B-tree with a high branching factor b is log_b(n) deep — same idea, fatter halving. That's why a 4-level B-tree can index millions of rows.
  • Binary heaps: sift-up and sift-down walk one root-to-leaf path. Path length = tree height = O(log n).
  • Divide and conquer: merge sort splits the array in half each level, giving log₂(n) levels of O(n) work → O(n log n). The log factor is the number of splits.
  • Bits: the number of bits to represent n is ⌈log₂(n+1)⌉. "How many bits?" and "how many halvings?" are literally the same question.
  • Exponential search / doubling: when you double a buffer or probe 1, 2, 4, 8, …, you reach n in log₂(n) steps. Halving, run backwards.

"But my data isn't a power of two"

Real inputs aren't clean powers of 2, and the base isn't always 2 — a ternary split is log₃, a B-tree with branching factor 256 is log₂₅₆. When you need the actual value for a back-of-the-envelope estimate, you lean on the change-of-base formula:

log_b(n) = ln(n) / ln(b) = log₁₀(n) / log₁₀(b)

So the depth of a B-tree holding 10 million keys with a branching factor of 256 is log₂₅₆(10,000,000) = ln(10,000,000) / ln(256) ≈ 16.1 / 5.55 ≈ 2.9 — three levels. You can punch that into any logarithm calculator that supports an arbitrary base instead of reaching for a language's math.log(x, base) mid-discussion. The point isn't the tool; it's that base is just branching factor, and change-of-base lets you compare a binary split against a 256-way split on the same axis.

One more identity worth keeping: in Big-O, the base doesn't matter. log₂(n) and log₁₀(n) differ only by the constant factor 1/ln(2) vs 1/ln(10), and Big-O eats constants. That's why we write O(log n) with no base at all — the existence of halving is what we're claiming, not its flavor.

The takeaway

Next time you read O(log n), don't translate it to "fast." Translate it to "this algorithm halves the problem every step," and ask where the halving happens — the comparison, the tree level, the recursive split, the doubling buffer. That single reframing turns binary search, balanced trees, heaps, and divide-and-conquer into variations on one theme instead of four things to memorize.

Halving is the cheapest superpower in computer science. Logarithms are just how we count it.