Maximum Product of Two Digits ā š“ Advanced (3/3) ā LeetCode Daily Python Solution (swap one digit, +60)
š Jump to your level: š“ Advanced: 0:18ā3:50 š Full written solution: https://interview-kit-fe.vercel.app/maximum-product-of-two-digits-advanced š» Code on GitHub: https://github.com/timepasshub2539-hue/leetcode-python/tree/main/maximum-product-of-two-digits-advanced Chapters: 0:00 The Problem: Maximum Product of Two Digits 0:18 š“ Advanced: Swap one digit, the answer jumps by 60 0:32 This exact pattern powers real systems 0:44 What are we actually asked? 0:57 Meet the tools 1:08 The core idea: track the top two 1:23 The obvious approach first 1:35 Step one: split n into digits 1:47 Step two: track top two as we go 2:05 Step three: return the product 2:15 Pause: what does this return for 22? 2:26 Here's the aha moment 2:41 Complexity: one pass wins 2:53 When would you actually pick brute force? 3:10 Edge cases the code must survive 3:26 Recap: the two-tracker trick 3:38 That's a wrap for today 3:50 Quick Quiz! 3:57 ... 4:00 Answer! 4:06 Round 2! 4:14 ... 4:19 Answer! We solve Maximum Product of Two Digits step by step in Python: how swapping a single digit swings the answer by 60, why real systems rely on this exact top-two pattern, and how to build the solution from splitting digits to tracking the top two in one pass. You'll see the brute-force approach first, then the aha moment that turns it into an O(n) one-pass trick, plus the edge cases your code has to survive. Ends with a quick quiz to test what you learned. #LeetCode #Python #CodingInterview #DSA #LeetCodeDaily Watch next: - Sequential Digits Explained in Python ā Sliding Window Over a String (LeetCode 1291): https://youtu.be/wgMhwxSzuKg - Lesson 11: Why Does return None Happen to Everyone?: https://youtu.be/uTHuP6xhP5M - Stop Copy-Pasting Your Own Code #shorts: https://youtu.be/CyX0a6fKeZg
Introduction
Every developer runs into problems that look small on the surface but hide a much bigger idea underneath. Maximum Product of Two Digits is exactly that kind of problem. On the surface, it's asking you to pull two digits out of a number and multiply them for the biggest possible result. Underneath, it's testing something interviewers care about a lot more: can you track the "top two" values in a single pass without reaching for a heap, a sort, or nested loops?
This pattern shows up constantly outside of interviews too. Bidding engines that need the top two bids, leaderboards that display the top two scores, monitoring systems that flag the two highest latency spikes ā all of these use the exact same mental model you'll build here. Learning to solve this problem well isn't just about passing a LeetCode question. It's about internalizing a technique you'll reuse for the rest of your career: constant-space top-k tracking when k is small and fixed.
By the end of this article, you'll understand not just how to write the solution, but why the order of your comparisons matters, why duplicate digits don't need special-case handling, and how this problem sets you up for the natural follow-up question every interviewer eventually asks.
Problem Overview
You're given a positive whole number n. Your task is to look at every digit in that number and find the two digits whose product is the largest possible.
The important rule: if a digit appears more than once in the number, you're allowed to use each occurrence as a separate, independent digit. So if the number contains two 9s, you can multiply 9 Ć 9 ā you are not restricted to picking distinct digit values.
There's no negative sign to worry about, no decimal points, and no digits outside the 0ā9 range. You just need to break the number down into its digits and figure out which two, multiplied together, give the maximum result.
Example
Example 1:
Input: n = 199
Output: 81
The digits are 1, 9, 9. The two largest digits are 9 and 9 (the two separate occurrences of 9 count individually). Multiplying them gives 9 Ć 9 = 81.
Example 2:
Input: n = 22
Output: 4
The digits are 2, 2. Both digits are 2, so the maximum product is 2 Ć 2 = 4. This is the classic edge case: every digit is a duplicate, and your solution still has to produce the right answer without any special-case branch for equal values.
Example 3:
Input: n = 508
Output: 40
The digits are 5, 0, 8. The two largest are 8 and 5, giving 8 Ć 5 = 40. Notice the 0 digit doesn't break anything ā it's simply never picked because it's never among the top two.
Intuition
The naive instinct when you see "two digits, maximum product" is to reach for position: grab the first two digits, or the last two, or sort the whole number as a string and slice the ends. That instinct is the trap. The problem never says anything about position ā it says "any two digits." What you actually need are the two largest values in the digit list, regardless of where they sit.
Once you reframe it that way, the problem becomes a specific case of a much more general pattern: finding the top-k elements in a stream. When k is large or variable, you'd typically reach for a min-heap of size k, popping the smallest whenever a bigger element shows up. But here, k is fixed at exactly 2. That's small enough that you don't need a heap at all ā you can just hardcode two variables, max1 and max2, and update them as you scan.
The subtlety that trips people up is the update order. You want to always keep max1 >= max2. So when you see a new digit:
- If it's bigger than
max1, it becomes the newmax1, and the oldmax1slides down to become the newmax2. - Otherwise, if it's bigger than
max2(but notmax1), it just replacesmax2.
This cascading order is what makes duplicates work automatically. Take n = 22. On the first 2, it beats max1 (which starts at 0), so max1 becomes 2 and max2 stays 0. On the second 2, it does not beat max1 (they're equal, and the check is strict >), but it does beat max2 (2 > 0), so max2 becomes 2 too. Now both trackers hold 2, and the product is 4 ā exactly right, with no special "handle equal digits" branch anywhere in the code.
Brute Force Solution
Idea: Extract every digit into a list, then check every possible pair of digits and keep the maximum product.
Algorithm:
- Convert the number to its list of digits.
- Use two nested loops to consider every pair
(i, j)wherei != j. - Track the maximum product seen across all pairs.
Advantages:
- Dead simple to write and reason about.
- Naturally extends if the problem changed to "return every pair's product" instead of just the max.
- Useful if you needed the indices of both chosen digits rather than just their values.
Disadvantages:
- Doesn't demonstrate that you understand the top-k generalization, which is almost certainly the interviewer's follow-up.
- Wasted work: you're comparing pairs you already know can't beat the top two.
Complexity: O(n²) time where n is the number of digits, O(n) space to hold the digit list. Since a number is bounded to about 10-11 digits at most, this runs in well under a microsecond in practice ā the complexity here is a signaling issue in an interview, not a performance issue.
Optimal Solution
The optimal approach tracks the two largest digits seen so far in a single pass, using two variables instead of any data structure.
Here's the state you carry as you scan the digits of n = 199:
| Digit seen | Check | max1 | max2 |
|---|---|---|---|
| start | ā | 0 | 0 |
| 1 | 1 > 0 ā yes |
1 | 0 |
| 9 | 9 > 1 ā yes |
9 | 1 |
| 9 | 9 > 9? no. 9 > 1? yes |
9 | 9 |
Final answer: max1 * max2 = 9 * 9 = 81.
The key invariant: max2 starts at 0 and only ever updates on a strict > comparison against max2 itself ā never against max1. That single design choice is what makes ties and duplicates fall out correctly without any extra logic.
Python Code
def max_product(n: int) -> int:
"""Return the maximum product of any two digits in n."""
max1 = max2 = 0
for char in str(n):
digit = int(char)
if digit > max1:
max1, max2 = digit, max1 # old max1 cascades down to max2
elif digit > max2:
max2 = digit
return max1 * max2
if __name__ == "__main__":
assert max_product(199) == 81
assert max_product(22) == 4
assert max_product(508) == 40
assert max_product(10) == 0
assert max_product(5) == 0 # single digit, no valid second digit -> 0
print("all checks passed")
Code Walkthrough
max1 = max2 = 0ā both trackers start at zero, which safely handles the "no digit found yet" state since digits are always non-negative.for char in str(n)ā converts the number to a string so we can iterate its digits one character at a time.digit = int(char)ā converts each character back to an integer for comparison and multiplication.if digit > max1ā strict comparison. If the new digit beats the current leader, we promote it tomax1and demote the oldmax1down tomax2in one line via tuple assignment.elif digit > max2ā only runs if the digit didn't beatmax1. If it beats the second-place tracker, it takes that spot.return max1 * max2ā the only line where both trackers are used together; everything before this was bookkeeping.
Dry Run
Let's trace n = 199 step by step.
- Start:
max1 = 0,max2 = 0 - Digit
1:1 > 0is true āmax1 = 1,max2 = 0(old max1) - Digit
9:9 > 1is true āmax1 = 9,max2 = 1(old max1) - Digit
9:9 > 9is false ā checkelif 9 > 1ā true āmax2 = 9 - Final:
max1 = 9,max2 = 9ā9 * 9 = 81
Matches the expected output.
Complexity Analysis
Time: O(n), where n is the number of digits in the input. Each digit is visited exactly once, and every operation inside the loop is O(1).
Space: O(1) extra space. We only ever hold two integer variables regardless of how many digits the number has. (Technically str(n) allocates a string of length n, but that's the input representation, not extra working state ā and even that can be avoided by extracting digits with % 10 and // 10 if you want to skip the string allocation entirely.)
This is correct because at every point in the loop, max1 and max2 hold the two largest digits seen so far, which is an invariant maintained by the cascade-on-max1, replace-on-max2 update rule ā by the time the loop ends, they hold the two largest digits overall.
Alternative Solutions
You could pull digits using arithmetic (n % 10, n //= 10) instead of string conversion, avoiding the string allocation entirely. At the input sizes this problem allows (n ⤠10^10 or so), this makes no measurable difference ā but it's worth mentioning if an interviewer asks about avoiding unnecessary allocations.
You could also generalize immediately to a min-heap of size k and set k = 2. This is overkill for this exact problem, but it's the natural bridge to the follow-up question: "what if you needed the top k digits instead of just two?" At that point, the two-variable trick stops scaling and a heap becomes the right tool.
Edge Cases
- Single-digit number (e.g.,
n = 5): There's only one digit, somax2never updates past0, and the product is0. Worth clarifying with your interviewer whether this is valid input or whethernis guaranteed to have at least two digits. - All duplicate digits (e.g.,
n = 22,n = 999): Handled automatically by the strict-inequality cascade ā no special casing needed. - A zero digit present (e.g.,
n = 10): Zero is never selected as one of the top two unless every other digit is also zero, since any nonzero digit beats it. - Maximum-length input: Even at the largest number size allowed by constraints, the algorithm stays O(n) with constant extra space ā no degradation.
- Digits already in descending order (e.g.,
n = 987): First digit setsmax1, second digit correctly cascades intomax2, third digit is ignored since it beats neither tracker.
Common Mistakes
- Checking
max2beforemax1. If you test the new digit againstmax2first, you can overwrite the wrong tracker and break the invariant thatmax1 >= max2. - Using
>=instead of>. This looks harmless but changes which occurrence "wins" in tie situations and can cause subtly wrong cascading. - Special-casing
digit == max1. It feels intuitive to add a branch for exact ties, but theelif digit > max2branch already covers this correctly ā adding a special case is redundant and a common source of bugs. - Reaching for position instead of value. Grabbing the first two or last two digits of the string ignores the actual problem statement ā you want the two largest values, not the two digits at specific indices.
- Forgetting digits can repeat. Some candidates try to deduplicate digits before comparing, which silently breaks inputs like
n = 22.
Interview Questions
- What if you needed the top 3 (or top k) digits instead of just 2? (Answer: switch to a min-heap of size k.)
- What if the input were a list of arbitrary integers instead of digits of a single number ā does your approach still work?
- Can you solve this without converting the number to a string at all?
- What's the smallest input for which brute force and the optimal solution differ in runtime in any noticeable way?
- How would you modify this to return the indices of the two digits instead of their product?
Similar Problems
- Third Maximum Number (LeetCode 414) ā same top-k tracking pattern, extended to k = 3.
- Kth Largest Element in an Array (LeetCode 215) ā the general case where a heap or quickselect becomes necessary.
- Maximum Product of Three Numbers (LeetCode 628) ā tests the same "track the extremes as you scan" intuition, complicated by negative numbers.
- Two Sum (LeetCode 1) ā a different pairing problem, but shares the lesson that single-pass tracking beats nested loops when possible.
Key Takeaways
The real lesson here isn't the two lines of arithmetic ā it's the discipline of recognizing a top-k problem in disguise and picking the right-sized tool for a fixed, small k. Two variables and a carefully ordered pair of comparisons replace an entire heap. Get the branch order right, and duplicate values, ties, and zero digits all resolve themselves without a single extra line of special-case code. That's the kind of solution that signals real understanding in an interview, not just a working answer.
Watch the Video
If you want to see this solution built up live, step by step, including the brute-force detour and the moment the top-two tracking trick clicks, check out the full walkthrough here: {LINK}
About the Series
This breakdown is part of the Daily Python LeetCode series, where each problem is solved from first principles in Python ā starting with the naive approach, building the intuition for the optimal one, and connecting it to the broader patterns that show up again and again in real interviews.
Call To Action
If this helped make the top-two tracking pattern click, give the video a like on YouTube and subscribe so you don't miss the next problem in the series. Subscribe to the Substack for the full written breakdown delivered straight to your inbox, and drop a comment with your own trace of n = 22 or n = 199 ā seeing how you worked through it helps shape what gets covered next. Sharing this with a friend prepping for interviews helps the series grow too.
The solution
def brute(n):
d = [int(c) for c in str(n)]
best = 0
for i in range(len(d)):
for j in range(len(d)):
if i != j:
best = max(best, d[i]*d[j])
return bestReady to try it yourself? Solve General problems with instant feedback in the practice sandbox.
Practice now ā


