Median of Two Sorted Arrays ā LeetCode Daily Python Solution (the trick nobody sees)
š Jump to your level: š¢ Beginner: 0:14ā8:06 š” Intermediate: 8:06ā12:28 š“ Advanced: 12:28ā17:14 š Full written solution: https://interview-kit-fe.vercel.app/median-of-two-sorted-arrays š» Code on GitHub: https://github.com/timepasshub2539-hue/leetcode-python/tree/main/median-of-two-sorted-arrays Chapters: 0:00 The Problem: Median of Two Sorted Arrays 0:14 š¢ Beginner: One simple idea solves this 'Hard' problem 0:36 Why bother learning this one 1:00 What exactly are we trying to do 1:36 A few words we'll keep using 2:08 The easy-but-slow way: just combine everything 2:24 Why the easy way isn't good enough 2:53 The trick: cut, don't combine 3:28 Getting ready for the binary search 3:58 The main loop, part 1: making a guess and looking around 4:38 The main loop, part 2: checking the guess and adjusting 5:10 Your turn: pause and predict 5:31 The answer, worked out: it's 2 6:06 How to talk about this in a real interview 6:32 Comparing the two approaches 6:58 Making sure it still works in tricky cases 7:28 Let's recap what we learned 8:06 š” Intermediate: One line of math kills this Hard problem 8:18 Why this problem actually matters 8:36 What are we actually asked to do 8:50 Tools we'll use 9:05 The brute force: just merge it 9:20 Where brute force breaks 9:30 Here's the trick: partition, don't merge 9:47 Set up the binary search 10:08 The core loop: guess and check 10:30 The core loop: decide and move 10:51 Pause: what breaks first? 11:02 The answer: it lands on 2 11:16 What you'd actually say in the interview 11:35 Complexity: pick your trade-off 11:53 Edge cases that must survive 12:09 Recap: the cut, not the merge 12:28 š“ Advanced: One line of math kills this Hard problem 12:45 Why this problem actually matters 13:01 What are we actually asked to do 13:17 Tools we'll use 13:32 The brute force: just merge it 13:44 Where brute force breaks 13:56 Here's the trick: partition, don't merge 14:21 Set up the binary search 14:38 The core loop: guess and check 14:57 The core loop: decide and move 15:12 Pause: what breaks first? 15:26 The answer: it lands on 2 15:46 What you'd actually say in the interview 16:06 Complexity: pick your trade-off 16:28 Edge cases that must survive 16:46 Recap: the cut, not the merge 17:14 Quick Quiz! 17:24 ... 17:26 Answer! 17:35 Round 2! 17:44 ... 17:47 Answer! Median of Two Sorted Arrays is one of LeetCode's most feared 'Hard' problems ā but it collapses into a few lines once you stop merging and start partitioning. This video walks through the brute-force merge approach, why it's too slow, and the binary-search-on-partitions trick that gets you to O(log(min(m,n))). Beginner, Intermediate, and Advanced walkthroughs included, plus a worked example, interview talking points, edge cases, and a quiz to test yourself. #LeetCode #MedianOfTwoSortedArrays #Python #CodingInterview #BinarySearch Watch next: - Sorted GCD Pair Queries ā LeetCode Daily Python Solution (5 Billion Pairs, No List): https://youtu.be/JVLzC_apwYQ - š” Intermediate: 1500 Numbers, But Only This Many Possible Answers #shorts: https://youtu.be/TX3u0SvF89k - Alternative: Just Run the Brute Force #shorts: https://youtu.be/YOVMM95a6xk
Introduction
Median of Two Sorted Arrays has a reputation. It's one of the few problems LeetCode tags as "Hard" that also shows up constantly in interviews at large tech companies, and the reason isn't that the code is long ā the final solution is barely twenty lines. The reason is that almost everyone's first instinct is wrong for the constraints being asked.
Most people can solve this problem in O(m + n) time in under a minute: merge the arrays, find the middle. The interviewer already expects that. What they're testing is whether you can recognize that merging is unnecessary ā that you can reason about the position of the median without ever touching most of the data. That skill, binary searching over an abstract "answer space" instead of a concrete array index, is one of the most reusable patterns in algorithm interviews. It reappears in problems about kth-smallest elements across multiple lists, capacity-to-ship-in-days problems, and split-array-largest-sum problems. Learning it once here pays off many times later.
Problem Overview
You're given two arrays, nums1 and nums2, and both are already sorted in ascending order. Your job is to find the median of the combined set of all their elements ā as if you had merged both arrays into one sorted array and then picked the middle value (or averaged the two middle values, if the total count is even).
The twist that makes this "Hard" is the required time complexity: O(log(min(m, n))), where m and n are the lengths of the two arrays. That rules out actually merging the arrays, and it even rules out a straightforward O(m + n) single pass. You need an approach whose running time barely grows even as the arrays get enormous ā and that's a strong signal the problem wants binary search.
Example
nums1 = [1, 3]
nums2 = [2]
Merged conceptually: [1, 2, 3]. Three elements total, so the median is the single middle value: 2.
A second example with an even total:
nums1 = [1, 2]
nums2 = [3, 4]
Merged conceptually: [1, 2, 3, 4]. Four elements, so the median is the average of the two middle values, 2 and 3: 2.5.
Notice both arrays stay untouched in memory in the real solution ā these merged lists are just how we're reasoning about the expected answer, not something the algorithm actually builds.
Intuition
Here's how an engineer who's seen binary-search-on-answer problems before would approach this.
The brute-force instinct is to physically build the merged array and index into the middle. That's correct, but it processes every element ā O(m + n) ā and the problem is explicitly asking for something logarithmic. Logarithmic time is a strong hint: it usually means "you can throw away half of your remaining search space at each step," which is the definition of binary search. But binary search over what? There's no single sorted array to search over.
The insight is that instead of searching for a value, you can search for a position ā specifically, a way to slice both arrays simultaneously so that everything to the left of both cuts, combined, is exactly the left half of the total elements, and everything to the right is the right half.
Picture both arrays as two rows of cards. You slide one divider through each row at the same time. If you can find dividers such that:
- every card left of either divider is ⤠every card right of either divider
...then you've found the correct partition, and the median sits right at that boundary ā no merging needed. You only ever need to look at four cards: the one just left and just right of each divider.
Since a valid divider position in nums1 fully determines the required divider position in nums2 (the two must add up to exactly half the total count), you only need to binary search one array ā and to keep the search space as small as possible, you always binary search the shorter array. That's where O(log(min(m, n))) comes from.
Brute Force Solution
Idea: Merge both arrays into one sorted array, then index into the middle.
Algorithm:
- Merge
nums1andnums2using a standard two-pointer merge (like the merge step of merge sort). - If the total length is odd, return the single middle element.
- If even, return the average of the two middle elements.
Advantages: Trivial to write and reason about; easy to verify by hand.
Disadvantages: Touches every element, and allocates extra memory for the merged array ā both violate the problem's required complexity.
Complexity: Time O(m + n), Space O(m + n).
Optimal Solution
We binary search over how many elements of the shorter array (call it nums1, after swapping if needed) go into the left half of the final merged sequence. Call that count i. Because the left half must always contain exactly half = (m + n + 1) // 2 elements total, the matching count from nums2 is forced: j = half - i.
At any guess i, we look at four border values:
| Name | Meaning | Value if out of bounds |
|---|---|---|
left1 |
last element in nums1's left partition | -infinity if i == 0 |
right1 |
first element in nums1's right partition | +infinity if i == m |
left2 |
last element in nums2's left partition | -infinity if j == 0 |
right2 |
first element in nums2's right partition | +infinity if j == n |
The partition is correct when left1 <= right2 and left2 <= right1. If left1 > right2, we included too many elements from nums1 on the left, so we move the guess i down. Otherwise, we move it up. This is standard binary search, just applied to a partition count instead of an array index.
Once the correct partition is found:
- If the total length is odd, the median is
max(left1, left2). - If even, the median is the average of
max(left1, left2)andmin(right1, right2).
The (m + n + 1) // 2 formula (note the +1) is what makes both the odd and even cases fall out of the same code path without a separate branch ā for odd totals, the left half simply ends up one element larger, which is exactly the extra element the odd-case return picks up.
Python Code
from typing import List
def find_median_sorted_arrays(nums1: List[int], nums2: List[int]) -> float:
# Always binary search the shorter array to minimize the search space.
if len(nums1) > len(nums2):
nums1, nums2 = nums2, nums1
m, n = len(nums1), len(nums2)
half = (m + n + 1) // 2
lo, hi = 0, m
while lo <= hi:
i = (lo + hi) // 2 # partition index in nums1
j = half - i # forced partition index in nums2
left1 = nums1[i - 1] if i > 0 else float("-inf")
right1 = nums1[i] if i < m else float("inf")
left2 = nums2[j - 1] if j > 0 else float("-inf")
right2 = nums2[j] if j < n else float("inf")
if left1 <= right2 and left2 <= right1:
if (m + n) % 2 == 1:
return max(left1, left2)
return (max(left1, left2) + min(right1, right2)) / 2
elif left1 > right2:
hi = i - 1
else:
lo = i + 1
raise ValueError("Input arrays must be sorted")
Code Walkthrough
- Swap step: guarantees
nums1is the shorter (or equal-length) array, which is what keepsjguaranteed to land inside[0, n]for everyiwe try. half: the required size of the combined left half, computed once outside the loop.lo, hi = 0, m: the binary search range is over how many elements ofnums1to place on the left ā not over values, and not overnums1's indices in the usual sense.iandj:iis our guess;jis derived, not guessed, since the two must always sum tohalf.- Sentinel infinities: let a partition sit exactly at an array's start or end without special-casing ā there's simply "nothing" on that side, and infinity/negative-infinity behave correctly in comparisons.
- The condition:
left1 <= right2 and left2 <= right1is the correctness check. Note the code never explicitly checks the reverse direction as a third branch ā ifleft1 > right2fails,left2 > right1is the only remaining failure mode, so theelsecovers it. - Median extraction: odd totals take the max of both left values; even totals average that max with the min of both right values.
Dry Run
nums1 = [1, 3], nums2 = [2]. Already nums1 is the shorter array, so no swap. m = 2, n = 1, half = (2 + 1 + 1) // 2 = 2.
lo = 0, hi = 2. First guess: i = 1, so j = half - i = 1.
left1 = nums1[0] = 1right1 = nums1[1] = 3left2 = nums2[0] = 2right2 = +inf(j == n, nothing left in nums2)
Check: left1 (1) <= right2 (inf) ā, left2 (2) <= right1 (3) ā. Partition is valid.
Total length m + n = 3 is odd, so return max(left1, left2) = max(1, 2) = 2.
Matches the expected answer from merging by hand: [1, 2, 3] ā median 2.
Complexity Analysis
Time: O(log(min(m, n))) ā the binary search only ever runs over the shorter array's index range, halving the range each iteration; j is computed in O(1), not searched.
Space: O(1) ā no merged array, no auxiliary data structures; only a handful of scalar variables.
Why these are correct: because both arrays are individually sorted, moving i monotonically moves left1/right1 monotonically as well. That monotonicity is exactly what guarantees binary search converges to the correct partition rather than getting stuck or oscillating.
Alternative Solutions
A reasonable middle ground between brute force and the optimal partition trick is a two-pointer "count to the middle" walk: advance pointers through both arrays simultaneously, counting elements, and stop once you've passed the halfway point, tracking the last one or two values seen. This avoids allocating a merged array (O(1) space) but still runs in O(m + n) time, since it walks roughly half of the combined elements. It's a fine fallback if you're asked to solve this without hitting logarithmic time, and it's a good way to sanity-check the partition solution against a smaller, easier-to-trust approach.
Edge Cases
- One array is empty: the sentinel infinities take over ā the divider index for the empty array pins to
0for its entire binary search, and the logic still holds. - Arrays of very different lengths: handled automatically, since we always binary search the shorter array regardless of how large the other one is.
- Duplicate values across both arrays: the
<=comparison (not strict<) correctly allows ties at the cut boundary. - Single-element arrays: works the same way ā
iandjcan only be0or1, and the sentinels handle both boundary positions. - Total length is even vs. odd: both handled by the same
(m + n + 1) // 2formula without a separate code path for each case.
Common Mistakes
- Binary searching the longer array instead of the shorter one. This can push
joutside a valid range and requires extra bounds handling that the shorter-array approach avoids entirely. - Forgetting the sentinel infinities, causing index-out-of-range errors when a partition sits at an array's edge.
- Using strict
<instead of<=in the validity check, which incorrectly rejects valid partitions when duplicate values sit right at the cut. - Miscomputing
halfā dropping the+1breaks the odd-length case, since the left half needs to be one element larger for odd totals. - Actually merging the arrays to "double check," then submitting that as the final solution ā it passes small test cases but fails the time complexity requirement on large inputs.
Interview Questions
- "Can you do better than O(log(min(m, n)))?" ā No, for arbitrary sorted arrays, you need at least that many comparisons to locate the correct partition boundary in the worst case.
- "What if
nums2were empty?" ājpins to0for the entire search, and the sentinel infinities onnums2's side handle it without any special-casing. - "How would you find the kth smallest element across two sorted arrays instead of the median?" ā Same invariant, different target size for the left half.
- "Why do we always search the smaller array?" ā Because the partition point in the larger array is derived from it; searching the larger array wastes steps and risks an invalid
j.
Similar Problems
- Kth Smallest Element in Two Sorted Arrays ā the exact same partition invariant, generalized to an arbitrary target rank instead of the median.
- Merge Sorted Array (LeetCode 88) ā the brute-force building block this problem asks you to avoid; useful for understanding why merging is O(m + n).
- Capacity To Ship Packages Within D Days ā another "binary search on the answer" problem, where you search a value range instead of an array index.
- Split Array Largest Sum ā same underlying pattern: binary search over a monotonic predicate rather than concrete indices.
Key Takeaways
Merging is the obvious first move, but it's the wrong tool once a problem explicitly asks for logarithmic time. The real lesson here is recognizing when you can binary search over an abstract quantity ā a partition count, a capacity, a target sum ā rather than over a literal array index. Once you spot that pattern, this "Hard" problem collapses into checking four numbers and nudging a guess left or right.
Watch the Video
For the full visual walkthrough ā including the card-and-divider mental model and a live trace of the binary search ā check out the video here: {LINK}
About the Series
This breakdown is part of the Daily Python LeetCode series, where one problem gets solved from first principles every day ā brute force first, then the optimal approach, with full Python code and a dry run every time. The goal is to build real intuition, not just memorize solutions.
Call To Action
If this helped the partition trick click, drop a like on the video ā it's the simplest way to tell me it landed. Subscribe on YouTube for tomorrow's problem, and subscribe to the Substack if you'd rather get the full write-up in your inbox. Comments with your own dry runs or alternative approaches are always welcome, and sharing this with someone prepping for interviews helps more than you'd think.
The solution
while lo <= hi:
i = (lo + hi) // 2
j = (m + n + 1) // 2 - i
left1 = nums1[i-1] if i > 0 else float('-inf')
right1 = nums1[i] if i < m else float('inf')
left2 = nums2[j-1] if j > 0 else float('-inf')
right2 = nums2[j] if j < n else float('inf')Ready to try it yourself? Solve Binary problems with instant feedback in the practice sandbox.
Practice now ā


