H-Index II — Binary Search on Sorted Citations [LC 275]
Advertisement
Problem Statement
LeetCode 275 — H-Index II · Difficulty: Medium
Given an array citations of integers sorted in non-decreasing order, where citations[i] is the number of citations a researcher received for their i-th paper, return the researcher's h-index.
The h-index is defined as the maximum value h such that the researcher has published at least h papers with at least h citations each.
Constraints:
n == citations.length1 <= n <= 10^50 <= citations[i] <= 1000citationsis sorted in non-decreasing order
Example 1:
Input: citations = [0, 1, 3, 5, 6]
Output: 3
Explanation: There are 5 papers. 3 papers have at least 3 citations each (citations[2]=3, [3]=5, [4]=6).
But NOT 4 papers have at least 4 citations (only 2 papers have >= 4).
So h-index = 3.Example 2:
Input: citations = [1, 2, 100]
Output: 2
Explanation: 2 papers have at least 2 citations ([1]=2, [2]=100).
3 papers do NOT all have >= 3 citations (citations[0]=1 < 3). So h = 2.Example 3:
Input: citations = [0, 0, 0]
Output: 0
Explanation: No paper has any citations. h-index = 0.Why This Problem Matters
H-Index II is a masterclass in translating a real-world metric into a binary search condition. The array is sorted, so there must be a binary search solution — but the condition is non-obvious. This is exactly what Google and Meta interviewers look for: can you derive the search condition yourself, rather than just applying a memorised template?
LC 274 (H-Index) solves the unsorted version in O(n log n) by sorting first. LC 275 (this problem) asks for O(log n) on the already-sorted array. The jump from O(n log n) to O(log n) requires recognising a monotone structure and expressing the h-index condition in terms of array indices — a skill that separates strong binary search practitioners from average ones.
The Core Insight
With n papers sorted in non-decreasing order by citations, if we pick index mid, then exactly n - mid papers have citations >= citations[mid] (all papers from index mid to n-1).
We want the smallest index mid such that citations[mid] >= n - mid.
Why? Because at that index, there are n - mid papers with at least n - mid citations. The h-index is then n - mid — the number of papers in the qualifying group.
The monotone property: once citations[mid] >= n - mid is true at some index, it remains true for all larger indices. So we can binary search for the leftmost index where this condition holds.
Boundary cases:
- If no index satisfies the condition (all citations are 0),
loends atn, andn - lo = 0— correct h-index of 0. - If all papers have high citations,
loends at 0, andn - 0 = n— every paper qualifies.
Visual Dry Run
Input: citations = [0, 1, 3, 5, 6], n = 5
We seek the smallest mid where citations[mid] >= n - mid = 5 - mid.
| Index | citations[i] | n - i | citations[i] >= n-i? |
|---|---|---|---|
| 0 | 0 | 5 | 0 >= 5? No |
| 1 | 1 | 4 | 1 >= 4? No |
| 2 | 3 | 3 | 3 >= 3? Yes |
| 3 | 5 | 2 | 5 >= 2? Yes |
| 4 | 6 | 1 | 6 >= 1? Yes |
Leftmost Yes is at index 2. h-index = n - 2 = 3. Correct.
Binary search trace:
| Step | lo | hi | mid | citations[mid] | n - mid | Condition | Decision |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 5 | 2 | 3 | 3 | 3 >= 3? Yes | hi = 2 |
| 2 | 0 | 2 | 1 | 1 | 4 | 1 >= 4? No | lo = 2 |
| 3 | lo=hi=2 | — | — | — | — | — | return n - lo = 3 |
Input: citations = [1, 2, 100], n = 3
| Step | lo | hi | mid | citations[mid] | n - mid | Condition | Decision |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 2 | 2 | 2 >= 2? Yes | hi = 1 |
| 2 | 0 | 1 | 0 | 1 | 3 | 1 >= 3? No | lo = 1 |
| 3 | lo=hi=1 | — | — | — | — | — | return n - 1 = 2 |
Common Mistakes
-
Binary searching on the h-value instead of the index — it is tempting to binary search on the value
hfrom 0 to n. This works but requires a linear scan per check (O(n log n) total). The O(log n) solution searches on the index directly. -
Using
hi = n - 1instead ofhi = n— the h-index could be 0, meaningloshould reachn(past the last index). Initialisinghi = n - 1prevents this and incorrectly returns a positive h-index even when citations are all 0. -
Confusing the condition direction — the condition
citations[mid] >= n - midmust hold to movehileft (we want the leftmostYes). Reversing tocitations[mid] < n - mid→lo = mid + 1is the else branch. Getting these backwards finds the wrong boundary. -
Not understanding what
n - lorepresents — after the search,lois the first index where the condition holds.n - locounts papers fromloton-1, each having>= n - locitations. This is the h-index by definition. -
Forgetting the all-zeros edge case —
citations = [0, 0, 0]should return 0. Withhi = n, the loop runs correctly andloends atn, givingn - n = 0. -
Mishandling ties in citations — if multiple papers have the same citation count, the leftmost-boundary search correctly finds the first position where the group is large enough.
-
Off-by-one when computing n - mid —
n - midcounts elements from indexmidinclusive to the end. Double-check: forn = 5andmid = 2, that is indices 2, 3, 4 → 3 papers.5 - 2 = 3. Correct.
Solutions
Python
def hIndex(citations: list[int]) -> int:
n = len(citations)
# Search for the leftmost index where citations[mid] >= n - mid.
# lo ranges over [0, n]; hi = n allows the result n - lo = 0.
lo, hi = 0, n
while lo < hi:
mid = lo + (hi - lo) // 2 # lower-mid for left-boundary search
# At index mid, there are (n - mid) papers with >= citations[mid] citations.
# If this count is at most citations[mid], this index qualifies.
if citations[mid] >= n - mid:
hi = mid # condition met: try to go further left
else:
lo = mid + 1 # condition not met: first valid index is to the right
# lo is the first qualifying index. n - lo papers form the h-index group.
return n - loJavaScript
function hIndex(citations) {
const n = citations.length;
// hi = n (not n-1) to handle the case where h-index is 0
let lo = 0, hi = n;
while (lo < hi) {
const mid = lo + Math.floor((hi - lo) / 2); // lower-mid for left-boundary
// n - mid papers exist from index mid to n-1.
// If citations[mid] >= n - mid, all those papers qualify.
if (citations[mid] >= n - mid) {
hi = mid; // valid: search left for an even earlier qualifying index
} else {
lo = mid + 1; // not valid: first qualifying index must be to the right
}
}
// lo is the leftmost qualifying index; n - lo is the h-index
return n - lo;
}Complexity Analysis
| Approach | Time | Space | Notes |
|---|---|---|---|
| Left-boundary binary search (this) | O(log n) | O(1) | Exploits sorted order directly |
| Binary search on h-value | O(n log n) | O(1) | Each check scans the array — slower |
| Linear scan from the right | O(n) | O(1) | Simpler but misses the O(log n) opportunity |
| H-Index I approach (sort then scan) | O(n log n) | O(1) | Already sorted here, unnecessary sort |
The binary search runs at most ceil(log₂(n+1)) iterations. For n = 10^5, that is at most 17 comparisons. Each comparison is O(1). Total time: O(log n).
Follow-up Questions
-
How does LC 274 differ? — LC 274 gives an unsorted array. You sort it first in O(n log n), then apply this same binary search. The sorted structure is what enables O(log n).
-
Why is
hiinitialised tonand notn-1? — The h-index can be 0 (no qualifying papers). Whenloreachesn,n - lo = 0correctly returns 0. Withhi = n-1, you can never reach this state. -
Can there be multiple valid h-index values? — By definition, the h-index is unique — it is the maximum h satisfying the condition. The binary search finds it exactly.
-
What if all citations are the same value, say c? — All
npapers haveccitations. The h-index ismin(c, n). Binary search converges to index 0 ifc >= n(h = n), or to some positive index otherwise. -
How would you modify this for descending-sorted citations? — Adjust the condition: at index
mid, there aremid + 1papers (from 0 to mid). Condition becomescitations[mid] >= mid + 1. Find the rightmost index where this holds.
This Pattern Solves
- LC 275 — H-Index II (this problem)
- LC 274 — H-Index (sort first, then same binary search)
- LC 35 — Search Insert Position (left-boundary: find where value belongs)
- LC 34 — Find First and Last Position (dual left/right boundary search)
- LC 278 — First Bad Version (left-boundary on a boolean predicate)
- Any problem where you need to find the leftmost index satisfying a monotone condition
Key Takeaway
H-Index II teaches a crucial binary search skill: translating a real-world optimisation condition into a binary comparison on indices. The key observation is that n - mid papers lie at or after index mid, so the condition citations[mid] >= n - mid tells us the qualifying group starts no later than mid. Binary search on this condition with left-boundary template (hi = mid on success) finds the answer in O(log n). Initialise hi = n (not n-1) to correctly handle the zero h-index case.
Key Takeaways
- LC 275 (H-Index II) converts a real-world academic metric into a left-boundary binary search; it tests index-arithmetic reasoning rather than algorithmic templates.
- The key observation: at any index
midin a sorted citations array, there are exactlyn - midpapers with citations >=citations[mid], since the array is ascending. - The binary condition
citations[mid] >= n - midis true when indexmidor earlier can anchor the h-index — search for the leftmost such index. - Use
hi = n(notn - 1) to allowloto settle atnwhen no paper qualifies, givingn - n = 0as the correct h-index. - The answer is
n - loafter the loop: the number of papers in the qualifying group starting at the leftmost valid index. - LC 274 (H-Index, unsorted version) requires sorting first in O(n log n) then applies this same binary search — LC 275 skips the sort.
- The left-boundary template (
hi = midon success,lo = mid + 1on failure) finds the earliest qualifying index in O(log n).
Advertisement