Maximum Product of Two Digits ā š” Intermediate (2/3) ā LeetCode Daily Python Solution (swap one digit, +60)
š Jump to your level: š” Intermediate: 0:19ā3:48 š Full written solution: https://interview-kit-fe.vercel.app/maximum-product-of-two-digits-intermediate š» Code on GitHub: https://github.com/timepasshub2539-hue/leetcode-python/tree/main/maximum-product-of-two-digits-intermediate Chapters: 0:00 The Problem: Maximum Product of Two Digits 0:19 š” Intermediate: 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:09 The core idea: track the top two 1:24 The obvious approach first 1:39 Step one: split n into digits 1:49 Step two: track top two as we go 2:02 Step three: return the product 2:13 Pause: what does this return for 22? 2:22 Here's the aha moment 2:36 Complexity: one pass wins 2:53 When would you actually pick brute force? 3:08 Edge cases the code must survive 3:23 Recap: the two-tracker trick 3:35 That's a wrap for today Today's LeetCode Daily Challenge: Maximum Product of Two Digits. We start with the brute-force way of checking every digit pair, then find the one-pass trick ā tracking just the top two digits as we scan ā that gets the same answer without nested loops. Along the way: why swapping a single digit can shift the result by 60, where this exact 'track the top-k' pattern shows up in real systems, and the edge cases that break naive solutions. Clean Python code, walked through step by step. #LeetCode #Python #CodingInterview #DSA #LeetCodeDaily Watch next: - š” Intermediate: One line of math kills this Hard problem #shorts: https://youtu.be/Kmj5GKYdEhQ - š” Intermediate: 1500 Numbers, But Only This Many Possible Answers #shorts: https://youtu.be/TX3u0SvF89k - š” Intermediate: One line of bit math kills this Medium problem #shorts: https://youtu.be/YupSe4GdSfY
Introduction
Every so often, LeetCode's Daily Challenge hands you a problem that looks trivial on the surface but is secretly testing something much more valuable: whether you reach for the first solution that works, or the right one. Maximum Product of Two Digits is exactly that kind of problem.
At a glance, it seems like a two-line brute-force exercise ā check every pair of digits, keep the biggest product, done. And for this specific problem, with numbers capped at ten digits, brute force will pass every test case without breaking a sweat. But interviewers don't ask this question to see if you can solve it. They ask it to see if you recognize the pattern underneath it: finding the top two values in a collection without sorting or comparing everything against everything else.
This "track the top two" idea isn't just an interview trick. It's the same logic that powers leaderboards showing champion and runner-up, bidding engines picking the two highest bids, and any system that needs the best few results out of a stream of data it can only see once. Learning to spot it here means you'll recognize it instantly the next time it shows up wearing a different costume.
Problem Overview
You're given a non-negative integer. Your task is to look at its individual digits and find two of them whose product is as large as possible. If a digit appears more than once in the number, you're allowed to use both copies ā so a number like 22 is a valid pair of digits, not a single digit counted twice by accident.
In plain terms: break the number into its digits, pick any two of them (repeats allowed), multiply them, and return the largest product achievable.
Example
Example 1
Input: n = 124
Digits: 1, 2, 4
Pairs and products:
1 Ć 2 = 2
1 Ć 4 = 4
2 Ć 4 = 8
Output: 8
The digit 4 and the digit 2 give the best product, 8. No other combination beats it.
Example 2
Input: n = 22
Digits: 2, 2
Output: 4
There's only one distinct digit, but since it appears twice, we're allowed to pair it with itself. 2 Ć 2 = 4.
Example 3
Input: n = 10
Digits: 1, 0
Output: 0
Any pair involving 0 collapses the product to zero, no matter what the other digit is. This is a common trap ā more on that in the edge cases section.
Intuition
Let's think about how an experienced engineer would approach this before writing any code.
The naive instinct is: "I need the product of two digits, so I need to check pairs." That's true, but it hides an important detail ā you don't actually need to know which two digits form the best pair. You only need to know the two largest digits in the number. Once you have those two values, multiplying them together automatically gives you the maximum product, because any other pairing would involve at least one smaller digit.
This is the same intuition behind picking a "champion" and "runner-up" on a leaderboard. As each new digit walks in, it either:
- Beats the current champion (and knocks the old champion down to runner-up), or
- Beats the runner-up but not the champion, or
- Doesn't beat anyone, and gets ignored.
If you walk through the digits once and maintain exactly these two slots, you'll always end up with the two largest digits ā without ever comparing digit pairs directly. That's the entire trick. No sorting, no nested loops, no extra memory beyond two variables.
Brute Force Solution
Idea: Check every possible pair of digits and keep track of the best product found.
Algorithm:
- Convert the number to a list of digits.
- Use two nested loops to generate every pair
(i, j)wherei != j. - Compute the product for each pair and track the maximum.
Advantages:
- Simple to write and easy to reason about.
- Guaranteed correct ā it literally checks everything.
Disadvantages:
- Wasteful. It performs far more comparisons than necessary.
- Doesn't scale. If this were generalized to "top two out of a huge list," quadratic comparisons would become a real bottleneck.
Time Complexity: O(n²), where n is the number of digits. Space Complexity: O(n) to store the digits (or O(1) if working directly on the number without a list).
Optimal Solution
Instead of comparing pairs, we scan the digits exactly once and maintain two running values: max1 (the largest digit seen so far) and max2 (the second largest).
Step-by-step logic for each digit d:
| Condition | Action |
|---|---|
d > max1 |
max2 becomes old max1, then max1 becomes d |
d <= max1 but d > max2 |
max2 becomes d |
| Otherwise | do nothing |
By the time we've scanned every digit, max1 and max2 hold the two largest digits in the number, and the answer is simply max1 * max2.
This works correctly even with repeated digits, because max2 starts at 0 and gets updated on ties ā a duplicate digit can still slide into the runner-up spot.
Python Code
def max_product(n: int) -> int:
"""Return the maximum product of any two digits in n (digit reuse allowed)."""
digits = [int(ch) for ch in str(n)]
max1 = max2 = 0
for d in digits:
if d > max1:
max1, max2 = d, max1
elif d > max2:
max2 = d
return max1 * max2
Code Walkthrough
digits = [int(ch) for ch in str(n)]ā converts the number into a string so we can iterate over each character, then converts each character back into an integer. This gives us a clean list of digits to scan.max1 = max2 = 0ā both trackers start at zero, since digits are always non-negative.if d > max1:ā if the current digit beats the champion, the old champion slides down intomax2and the new digit takes the top spot. Note the tuple assignmentmax1, max2 = d, max1ā this correctly demotes the oldmax1before overwriting it.elif d > max2:ā if the digit doesn't beat the champion but does beat the runner-up, it takes the second spot.return max1 * max2ā after one full pass, multiply the two largest digits found.
Dry Run
Let's trace n = 22.
| Step | Digit | max1 before | max2 before | Comparison | max1 after | max2 after |
|---|---|---|---|---|---|---|
| 1 | 2 | 0 | 0 | 2 > 0 ā true |
2 | 0 |
| 2 | 2 | 2 | 0 | 2 > 2 ā false; 2 > 0 ā true |
2 | 2 |
Final: max1 = 2, max2 = 2, product = 4. The repeated digit correctly slides into the runner-up spot instead of being ignored, which is exactly the case that trips up careless implementations.
Complexity Analysis
Time Complexity: O(n), where n is the number of digits. We scan the digit list exactly once, doing constant work per digit.
Space Complexity: O(1) extra space (excluding the input-to-digit-list conversion), since we only maintain two tracker variables regardless of how many digits there are.
This is correct because at every step, max1 and max2 always represent the two largest values seen so far ā an invariant that holds after processing each digit, and therefore holds at the end when all digits have been processed.
Alternative Solutions
You could also sort the digits in descending order and take the product of the first two:
def max_product_sorted(n: int) -> int:
digits = sorted((int(ch) for ch in str(n)), reverse=True)
return digits[0] * digits[1]
This is easy to read but runs in O(n log n) instead of O(n) due to the sort. For a number with at most ten digits, the difference is invisible in practice ā but it's worth knowing the tracker approach is the version that scales, since it's the pattern you'd want for "top two out of a million values" rather than "top two out of ten."
Edge Cases
- Single-digit repeated twice (e.g., 11):
max2still fills in correctly, giving a product of1. - Contains a zero (e.g., 10): The product correctly comes out to
0, since any pair involving zero collapses. - All identical digits (e.g., 999):
max1andmax2both end up as9, giving81. - Two-digit minimum input (e.g., 10): The loop still works correctly with exactly two digits.
- Large numbers with many digits: The loop doesn't care how many digits there are ā it scans once regardless of size, so performance stays linear.
Common Mistakes
- Forgetting digits can repeat. Some solvers try to find two distinct digit values and fail on inputs like
22. - Not demoting
max1correctly. Writingmax1 = dbefore updatingmax2overwrites the old champion before it can slide down, corrupting the tracker. - Initializing trackers incorrectly. Starting
max2at-1orNoneinstead of0can cause issues since digits are always non-negative ā0is a safe and correct baseline. - Defaulting to brute force out of habit. Nested loops work here, but the habit doesn't scale to "top-k" problems on much larger inputs.
- Confusing digit position with digit value. The problem is about digit values, not their positions in the number ā some solvers accidentally multiply digits by index instead of value.
- Not converting the number to digits properly. Forgetting to convert characters back to integers after the string split leads to string concatenation bugs instead of multiplication.
Interview Questions
- How would you generalize this to find the top k digits instead of just two?
- What changes if the input can contain negative numbers or is given as a list instead of an integer?
- Can you solve this without converting the number to a string?
- What's the tradeoff between this approach and sorting the digits first?
- How would you adapt this pattern to track the top two elements in a live data stream?
Similar Problems
- Third Maximum Number (LeetCode 414): Same "track the top-k trackers" pattern, extended to three values instead of two.
- Kth Largest Element in an Array (LeetCode 215): A generalized version of the top-k idea, often solved with heaps.
- Two Sum (LeetCode 1): Different goal, but shares the "single pass with tracking state" mindset instead of brute-force pairs.
- Maximum Subarray (LeetCode 53): Another problem where a naive nested-loop instinct gives way to a clean one-pass tracker (Kadane's algorithm).
Key Takeaways
When a problem asks for the "best two" of anything, resist the urge to compare every pair. Maintain two trackers, walk through the data once, and let each new value fight for the champion or runner-up spot. It's O(n) instead of O(n²), it uses constant extra space, and it's the exact same instinct you'll need for top-k problems, leaderboard systems, and streaming data pipelines later in your career.
Watch the Video
Want to see this solved step by step, including the moment where the brute-force temptation kicks in and why the tracker approach wins? Watch the full walkthrough here: {LINK}
About the Series
This breakdown is part of the Daily Python LeetCode series, where each day's LeetCode Daily Challenge gets solved in Python with a focus on the why behind the solution ā not just the code that passes the test cases. The goal is to build pattern recognition you can reuse across dozens of problems, not just memorize one answer.
Call To Action
If this breakdown helped the "top two tracker" pattern click for you, do three things: like the video on YouTube so more developers see it, subscribe so you don't miss tomorrow's problem ā where this same trick gets extended to three numbers instead of two ā and subscribe to the Substack newsletter for the full write-up delivered straight to your inbox. Drop a comment with how you originally solved it, and share this with a friend who's grinding through their own interview prep.
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 Dp problems with instant feedback in the practice sandbox.
Practice now ā


