Median of Two Sorted Arrays in O(log n): Which Premium AI Wins?
A classic hard algorithm: compute the median of two sorted lists in O(log(min(m,n))) time. A merge is explicitly disallowed, so the model must implement the tricky binary-search partition correctly — including empty-list and even/odd edge cases — and return code only. We sent this exact task to all 4 top-tier flagship models through the live API and measured real speed, cost, and accuracy. The full output of every model is included below — click any row to read it.
The prompt
Every model received exactly this (GLM 5.2 in Max reasoning mode, the others at default settings):
Write a Python function `median_of_two_sorted(a, b)` that returns the median of two already-sorted lists of numbers `a` and `b`. Requirements: - It must run in O(log(min(len(a), len(b)))) time. Do NOT merge the lists or sort the combined input (an O(m+n) solution is not acceptable). - The two input lists are each individually sorted in non-decreasing order. - Handle the case where one list is empty. - For an even total number of elements, return the average of the two middle values; for an odd total, return the single middle value. Always return a float. - Return ONLY the code inside a single Python code block, with no explanation.
How accuracy was graded
- Returns the correct median across thousands of randomized inputs and all edge cases.
- Achieves true O(log(min(m,n))) via a binary-search partition — no merging or sorting the combined input.
- Handles an empty input list and always returns a float.
- Returns only the code, with no explanation or leaked reasoning.
Results — sortable by speed, cost & accuracy
| # | Model | Accuracy ↓ | Speed ↕ | Cost ↕ | Output |
|---|---|---|---|---|---|
| 1 | GPT-5.4 ProOpenAI · gpt-5.4-pro | 100★ | 2.7 t/s206116 ms | $0.1032$180/M out | |
Agent grade — 100/100. Passes all 5,000+ randomized cases and every edge case; genuine O(log(min(m,n))) partition search, returns a float, code-only, and explicitly raises on two empty lists. Correct — but the slowest run by far (over three minutes), and now that real usage is reported, comfortably the most expensive. Verbatim output (152 in / 548 out tokens, 206116 ms, $0.1032) ```python
from math import inf
from typing import Sequence
def median_of_two_sorted(a: Sequence[float], b: Sequence[float]) -> float:
if len(a) > len(b):
a, b = b, a
n, m = len(a), len(b)
if n == 0 and m == 0:
raise ValueError("median is undefined for two empty lists")
total = n + m
half = (total + 1) // 2
left, right = 0, n
while left <= right:
i = (left + right) // 2
j = half - i
left_a = -inf if i == 0 else a[i - 1]
right_a = inf if i == n else a[i]
left_b = -inf if j == 0 else b[j - 1]
right_b = inf if j == m else b[j]
if left_a <= right_b and left_b <= right_a:
if total % 2 == 1:
return float(max(left_a, left_b))
return float((max(left_a, left_b) + min(right_a, right_b)) / 2.0)
if left_a > right_b:
right = i - 1
else:
left = i + 1
raise ValueError("input lists must be sorted in non-decreasing order")
``` | |||||
| 2 | Claude Opus 4.8Anthropic · claude-opus-4-8 | 100★ | 100.8 t/s3790 ms | $0.01065$25/M out | |
Agent grade — 100/100. Passes all 5,000+ randomized cases and every edge case; genuine O(log(min(m,n))) partition, float return, code-only. The fastest correct solution in this task. Verbatim output (220 in / 382 out tokens, 3790 ms, $0.01065) ```python
def median_of_two_sorted(a, b):
# Ensure a is the smaller list
if len(a) > len(b):
a, b = b, a
m, n = len(a), len(b)
total = m + n
half = (total + 1) // 2
lo, hi = 0, m
while lo <= hi:
i = (lo + hi) // 2 # elements taken from a
j = half - i # elements taken from b
a_left = a[i - 1] if i > 0 else float('-inf')
a_right = a[i] if i < m else float('inf')
b_left = b[j - 1] if j > 0 else float('-inf')
b_right = b[j] if j < n else float('inf')
if a_left <= b_right and b_left <= a_right:
if total % 2 == 1:
return float(max(a_left, b_left))
else:
return (max(a_left, b_left) + min(a_right, b_right)) / 2.0
elif a_left > b_right:
hi = i - 1
else:
lo = i + 1
raise ValueError("Input lists are not sorted or invalid")
``` | |||||
| 3 | GLM 5.2 (Max)Z.ai · glm-5.2 | 100★ | 45 t/s47713 ms | $0.009672$4.4/M out | |
Agent grade — 100/100. Passes all 5,000+ randomized cases and every edge case with a genuine O(log) partition and float return. The <think> block ahead of the code is GLM's reasoning channel surfaced by our gateway, not reasoning dumped into the answer — GLM's actual content is the clean code block — so it scores level with the other correct solutions, as the cheapest of them. Verbatim output (158 in / 2148 out tokens, 47713 ms, $0.009672) <think>
We need to write a Python function `median_of_two_sorted(a, b)` that returns the median of two sorted lists in O(log(min(len(a), len(b)))) time. The function should handle empty lists, return float, and for even total return average of two middle values, for odd return the single middle value.
We must implement the classic binary search on the smaller array. The algorithm: ensure a is the smaller array. Let m = len(a), n = len(b). We want to partition a and b such that left half contains elements <= right half. We binary search on partition index i in a (0 to m). Then j = (m + n + 1) // 2 - i. We need to ensure that a[i-1] <= b[j] and b[j-1] <= a[i] (with boundary checks). If condition holds, we found the correct partition. Then if total length is odd, median is max of left half. If even, median is (max(left) + min(right)) / 2.0.
Edge cases: empty arrays. If a is empty, median is just median of b. If b is empty, median of a. But the algorithm should handle it if we set a as the smaller array. If a is empty, m=0, then i=0, j = (0+n+1)//2 = (n+1)//2. Then we need to check conditions: a[i-1] doesn't exist, so we treat as -inf. b[j-1] <= a[i] (a[i] doesn't exist, treat as inf). So condition holds. Then left max is b[j-1] (if j>0) else -inf. Right min is b[j] (if j<n) else inf. Then compute median. This works.
We must return float. For odd total, return float(median). For even, return average as float.
Implementation details: Use integer indices. Use float('inf') and float('-inf') for boundaries.
Let's write the code.
```python
def median_of_two_sorted(a, b):
# Ensure a is the smaller array
if len(a) > len(b):
a, b = b, a
m, n = len(a), len(b)
# Binary search on a
low, high = 0, m
while low <= high:
i = (low + high) // 2
j = (m + n + 1) // 2 - i
# Get left and right elements with boundaries
a_left = a[i-1] if i > 0 else float('-inf')
a_right = a[i] if i < m else float('inf')
b_left = b[j-1] if j > 0 else float('-inf')
b_right = b[j] if j < n else float('inf')
if a_left <= b_right and b_left <= a_right:
# Found correct partition
if (m + n) % 2 == 1:
return float(max(a_left, b_left))
else:
return (max(a_left, b_left) + min(a_right, b_right)) / 2.0
elif a_left > b_right:
# i is too large, need to decrease i
high = i - 1
else:
# b_left > a_right, need to increase i
low = i + 1
# Should never reach here if inputs are sorted
raise ValueError("Input lists are not sorted or invalid.")
```
Check: For odd total, (m+n+1)//2 gives the size of left half (larger half). For even, left half size = (m+n)//2. The formula j = (m+n+1)//2 - i works for both: if total odd, left half has one more element, so j = (total+1)//2 - i. If total even, (total+1)//2 = total//2 (since total even, total+1 odd, integer division gives total//2). So j = total//2 - i. That's correct.
Test with examples:
a = [1, 3], b = [2] -> m=2, n=1. a is larger? Actually len(a)=2, len(b)=1, so we swap: a=[2], b=[1,3]. m=1, n=2. low=0, high=1. i=0: j=(1+2+1)//2 - 0 = 4//2=2. a_left=-inf, a_right=2, b_left=b[1]=3, b_right=inf. Check: a_left <= b_right (-inf <= inf) true. b_left <= a_right? 3 <= 2 false. So b_left > a_right, need to increase i. low=1. i=1: j=2-1=1. a_left=a[0]=2, a_right=inf, b_left=b[0]=1, b_right=b[1]=3. Check: 2<=3 true, 1<=inf true. Found. total=3 odd. max(2,1)=2. return 2.0. Correct.
a = [1, 2], b = [3, 4] -> m=2, n=2. low=0, high=2. i=1: j=(4+1)//2 -1 = 2-1=1. a_left=1, a_right=2, b_left=3, b_right=4. Check: 1<=4 true, 3<=2 false. b_left > a_right, increase i. low=2. i=2: j=2-2=0. a_left=2, a_right=inf, b_left=-inf, b_right=3. Check: 2<=3 true, -inf<=inf true. Found. total=4 even. max(2, -inf)=2, min(inf, 3)=3. avg=2.5. Correct.
Empty a: a=[], b=[1,2,3]. m=0, n=3. low=0, high=0. i=0: j=(0+3+1)//2 -0 = 4//2=2. a_left=-inf, a_right=inf, b_left=b[1]=2, b_right=b[2]=3. Check: -inf<=3 true, 2<=inf true. Found. total=3 odd. max(-inf,2)=2. return 2.0. Correct.
Empty both? Not specified but if both empty, m=0,n=0. low=0, high=0. i=0: j=(0+0+1)//2 -0 = 0. a_left=-inf, a_right=inf, b_left=-inf, b_right=inf. Check: -inf<=inf true, -inf<=inf true. Found. total=0 even? (0%2==0). max(-inf,-inf)=-inf, min(inf,inf)=inf. avg = (-inf+inf)/2 = nan. But problem likely assumes at least one element? Usually median of empty is undefined. We could handle by returning 0.0 or raising error. But requirements say "Handle the case where one list is empty." It doesn't mention both empty. We can leave as is, or add a check: if m==0 and n==0: return 0.0. But to be safe, we can just let it return nan, but better to handle. Since it's not specified, we can assume at least one list non-empty. But to be robust, we can add: if m == 0 and n == 0: return 0.0. However, the problem says "Handle the case where one list is empty." So both empty might not be tested. I'll include a check for both empty returning 0.0 or maybe raise ValueError. But the instruction says "Return ONLY the code inside a single Python code block, with no explanation." So we just provide the function. I'll add a guard: if not a and not b: return 0.0. But that might be unnecessary. Let's keep it simple.
Also, we need to ensure we return float. In Python, division / returns float. For odd case, we return float(max(...)). That's fine.
Time complexity: O(log(min(m,n))) because we binary search on the smaller array. Space O(1).
Let's write the final code block.
</think>
```python
def median_of_two_sorted(a, b):
# Ensure a is the smaller array for O(log(min(m, n))) complexity
if len(a) > len(b):
a, b = b, a
m, n = len(a), len(b)
# Edge case: both empty (not required, but safe)
if m == 0 and n == 0:
return 0.0
low, high = 0, m
while low <= high:
i = (low + high) // 2
j = (m + n + 1) // 2 - i
a_left = a[i - 1] if i > 0 else float('-inf')
a_right = a[i] if i < m else float('inf')
b_left = b[j - 1] if j > 0 else float('-inf')
b_right = b[j] if j < n else float('inf')
if a_left <= b_right and b_left <= a_right:
if (m + n) % 2 == 1:
return float(max(a_left, b_left))
else:
return (max(a_left, b_left) + min(a_right, b_right)) / 2.0
elif a_left > b_right:
high = i - 1
else:
low = i + 1
raise ValueError("Input lists are not sorted or invalid.")
``` | |||||
| 4 | Gemini 3.1 ProGoogle · gemini-3.1-pro | 99 | 18.4 t/s17413 ms | $0.004168$12/M out | |
Agent grade — 99/100. Passes all tests with a clean, minimal O(log) partition and float return, code-only. Docked one point only because two empty lists yield NaN rather than an explicit guard (not required by the prompt). Verbatim output (164 in / 320 out tokens, 17413 ms, $0.004168) ```python
def median_of_two_sorted(a, b):
if len(a) > len(b):
a, b = b, a
m, n = len(a), len(b)
low, high = 0, m
while low <= high:
partitionA = (low + high) // 2
partitionB = (m + n + 1) // 2 - partitionA
maxLeftA = float('-inf') if partitionA == 0 else a[partitionA - 1]
minRightA = float('inf') if partitionA == m else a[partitionA]
maxLeftB = float('-inf') if partitionB == 0 else b[partitionB - 1]
minRightB = float('inf') if partitionB == n else b[partitionB]
if maxLeftA <= minRightB and maxLeftB <= minRightA:
if (m + n) % 2 == 1:
return float(max(maxLeftA, maxLeftB))
else:
return (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2.0
elif maxLeftA > minRightB:
high = partitionA - 1
else:
low = partitionA + 1
``` | |||||
Verdict
On this advanced coding task, GLM 5.2 (Max) offered the best accuracy-for-money (100/100). The fastest answer came from Claude Opus 4.8 at 100.8 tokens/sec, while Gemini 3.1 Pro was cheapest to run — the priciest run here (GPT-5.4 Pro) cost roughly 25× as much for a comparable answer. When every model is this capable, the real question stops being “can it do it?” and becomes “how much time and money did the answer cost?” — expand the rows above to judge for yourself.
