Maximum Product of Two Elements in an Array โ ๐ด Advanced (3/3) โ LeetCode Python Solution (One Pass Trick)
๐ Jump to your level: ๐ด Advanced: 0:19โ4:21 ๐ Full written solution: https://interview-kit-fe.vercel.app/maximum-product-of-two-elements-in-an-array-advanced ๐ป Code on GitHub: https://github.com/timepasshub2539-hue/leetcode-python/tree/main/maximum-product-of-two-elements-in-an-array-advanced Chapters: 0:00 The Problem: Maximum Product of Two Elements in an Array 0:19 ๐ด Advanced: Two numbers. That's the whole problem. 0:35 Why interviewers love this one 0:50 What the problem actually asks 1:04 Think of a race, not an array 1:19 The intuition: bigger beats everything 1:37 Name it: the Top-Two Grab 1:50 The lazy version first 2:04 Why the end of the list? 2:15 The faster version: one pass 2:31 Why bump first into second? 2:47 Pause โ predict this 2:57 The reveal: it returns 1 3:14 The alternative: brute force 3:26 Cost check: which to pick 3:41 Edge cases it survives 4:01 Recap: only two ever mattered 4:21 Quick Quiz! 4:26 Think it through... 4:30 The one-pass wins 4:37 Round 2! 4:45 Don't rush it... 4:48 Yes, it still works The whole problem is two numbers โ so why do so many people over-think it? In this final part (3/3) of the Advanced walkthrough, we solve LeetCode's Maximum Product of Two Elements in an Array in Python. You'll see the lazy sort-first version, then the faster one-pass "Top-Two Grab" that tracks the two largest values in a single sweep. We predict a tricky output (spoiler: it returns 1), compare brute force vs one-pass cost, and stress-test the edge cases it quietly survives. Perfect for interview prep and anyone building real intuition instead of memorizing patterns. #LeetCode #Python #CodingInterview #DataStructures #Algorithms Watch next: - Why Can Arrays Jump Straight To Index 3? #shorts: https://youtu.be/S-kbE-Mx_gA - The Problem: Maximum Product of Three Numbers #shorts: https://youtu.be/2aTsEbj-o18 - Maximum Product of Three Numbers โ ๐ด Advanced (3/3) โ LeetCode Daily Python Solution (the two-negative trap): https://youtu.be/xmBpGBa7TEQ
SEO PACKAGE
1. SEO Title
Maximum Product of Two Elements in an Array โ LeetCode 1464 Python Solution (One-Pass O(n) Trick)
2. SEO Subtitle
Learn why finding the two largest numbers in a single sweep beats sorting โ and why this problem is really the K=2 case of top-K selection.
3. Featured Quote
"You don't need the whole array in order โ you just need the two biggest numbers. Everything else is wasted work."
4. Meta Description
Solve LeetCode 1464 Maximum Product of Two Elements in Python. Compare sorting vs a clean O(n) one-pass top-two scan, with dry runs and edge cases. (154 chars)
5. URL Slug
maximum-product-of-two-elements-in-array-leetcode-python
6. Keywords
- maximum product of two elements
- LeetCode 1464
- LeetCode Python solution
- coding interview
- one pass algorithm
- top two elements
- O(n) solution
- data structures and algorithms
- Python interview questions
- array algorithms
- greedy algorithm
- order statistics
- top-K selection
- time complexity analysis
- space complexity
- software engineering interview
- Python coding tutorial
- monotonic function
- sorting vs linear scan
- beginner Python algorithms
7. Tags
Python ยท LeetCode ยท Coding Interview ยท Algorithms ยท Data Structures ยท Arrays ยท Software Engineering ยท Interview Prep ยท Time Complexity ยท One Pass ยท Greedy ยท Order Statistics ยท Top K ยท Big O
8. Introduction
Some problems look intimidating and turn out to be simple. Others look simple and hide a lesson worth remembering. Maximum Product of Two Elements in an Array (LeetCode 1464) belongs to the second group. On the surface it's a one-line problem. Underneath, it's a clean test of whether you understand the difference between sorting your data and selecting from it โ a distinction that separates engineers who reach for the obvious tool from those who reach for the right one.
In a coding interview, nobody genuinely doubts you can solve this. The real signal an interviewer reads is how you solve it. Do you burn the phone screen on an O(n log n) sort because it's the first thing your fingers type? Or do you recognize that you only need the two largest values and grab them in a single O(n) pass?
This problem also quietly rewards people who read constraints carefully. There's a trap hidden in the difference between distinct indices and distinct values โ and a boundary assumption about non-negative numbers that makes the whole trick safe. Miss either, and you'll write code that returns the wrong answer on inputs the problem specifically allows.
By the end of this article you'll understand not just the solution, but why it's correct, when it generalizes, and how it connects to the broader top-K selection pattern you'll see again and again in algorithms and data structures work.
9. Problem Overview
You're given an array of integers, nums. Your job is to pick two elements at two different positions in the array. Call the values you picked a and b.
For each of them, subtract one. Then multiply the results:
$$(a - 1) \times (b - 1)$$
Return the largest possible value of that product over all valid pairs.
Two important details from the constraints:
- You choose two different indices, not two different values. If the same number appears twice, you're allowed to use both occurrences.
- Every value is at least 1. There are no zeros or negative numbers to worry about.
That second point matters more than it looks. Because every number is non-negative, subtracting one keeps things well-behaved, and the product can only grow as the chosen numbers grow. That single guarantee is what makes the shortcut in this problem valid.
10. Example
Example 1
Input: nums = [3, 4, 5, 2]
Output: 12
The two largest values are 5 and 4. We compute (5 - 1) * (4 - 1) = 4 * 3 = 12. No other pair can beat this, because any smaller pair produces smaller factors.
Example 2
Input: nums = [1, 5, 4, 5]
Output: 16
Here the value 5 appears twice, at two different positions. Since the problem only requires distinct indices, we're allowed to use both fives: (5 - 1) * (5 - 1) = 4 * 4 = 16.
Example 3 (the tricky one)
Input: nums = [2, 2]
Output: 1
Two equal values, two positions. The product is (2 - 1) * (2 - 1) = 1 * 1 = 1. A lot of people expect this to break โ it doesn't. Because we select two positions, the duplicate 2 legitimately fills both "largest" slots, and the answer is 1.
Example 4 (all ones)
Input: nums = [1, 1, 1]
Output: 0
Every value is the minimum, 1. So (1 - 1) * (1 - 1) = 0. This is a correct answer, not a bug โ worth remembering when we discuss edge cases.
11. Intuition
Let's build the reasoning the way an experienced engineer would, before writing a single line of code.
We want to maximize (a - 1) * (b - 1). The first instinct might be to try every pair. But look closer at the shape of the expression.
Define a simple transform: f(x) = x - 1. On our domain โ values that are always at least 1 โ this function is monotonically increasing. A bigger input always gives a bigger output. Nothing tricky, no dips.
Now, we're multiplying two of these transformed values together. Since every value is non-negative, both (a - 1) and (b - 1) are โฅ 0. When you're multiplying two non-negative numbers and you want the product as large as possible, you make each factor as large as possible, independently. There's no tension between the two choices, no trade-off โ bigger is always better on both sides.
And what makes (a - 1) largest? The largest a. What makes (b - 1) largest? The next-largest value. So:
The optimal pair is always the two largest numbers in the array.
That's the whole problem. The length of the array, n, is a red herring. You don't need to sort everything, you don't need every pairwise combination โ you just need the first and second largest values. In the language of algorithms, you want the 1st and 2nd order statistics, and nothing else.
โ ๏ธ Why non-negativity matters: This shortcut only works because values can't be negative. If negatives were allowed, two large negative numbers could multiply into a huge positive product โ so you'd also have to track the two smallest values. Because the problem guarantees everything is โฅ 1, we get to ignore that entirely.
12. Brute Force Solution
Idea: If we want the best pair, just try every pair.
Algorithm:
- Loop over every index
i. - For each
i, loop over every later indexj. - Compute
(nums[i] - 1) * (nums[j] - 1). - Keep the maximum seen.
def maxProduct(nums: list[int]) -> int:
best = 0
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
best = max(best, (nums[i] - 1) * (nums[j] - 1))
return best
Advantages:
- Impossible to get the logic wrong โ it literally checks everything.
- Generalizes to problems where the objective isn't separable (where you genuinely need to compare full pairs).
Disadvantages:
- Does a mountain of redundant work. For this monotonic product, comparing every pair is pure waste.
- Scales badly.
Complexity:
- Time:
O(nยฒ)โ nested loops over all pairs. - Space:
O(1).
This is the baseline you're beating. In an interview, mention it only to contrast, then move on.
13. Optimal Solution
We established that we only need the two largest values. There are two clean ways to get them.
Option A โ Sort and read the tail
Sort the array ascending, then the two largest sit at the end:
def maxProduct(nums: list[int]) -> int:
nums.sort()
return (nums[-1] - 1) * (nums[-2] - 1)
This is the honest one-liner. It's readable and hard to get wrong. But be ready to say two things out loud in an interview:
- It's
O(n log n)โ you're paying to fully order the array just to learn two facts about it. - It mutates the input in place. If the caller cares about immutability, flag it (use
sorted(nums)instead).
Option B โ One-pass "Top-Two Grab" (the trick)
Sweep the array once, keeping two registers: first (largest so far) and second (runner-up so far). Update them as you go.
The core idea is a cascade. When a new value beats the current champion:
- the old champion gets demoted to runner-up,
- the new value becomes champion.
That demotion is the entire correctness argument, and we'll see exactly why below.
Here's how the two registers evolve on nums = [3, 4, 5, 2]:
| Step | Value seen | first | second | Reasoning |
|---|---|---|---|---|
| init | โ | 0 | 0 | seeded at 0 (safe: values โฅ 1) |
| 1 | 3 | 3 | 0 | 3 beats first โ 0 demoted to second |
| 2 | 4 | 4 | 3 | 4 beats first โ old champ 3 demoted |
| 3 | 5 | 5 | 4 | 5 beats first โ old champ 4 demoted |
| 4 | 2 | 5 | 4 | 2 beats neither โ no change |
Final: (5 - 1) * (4 - 1) = 12. โ
This runs in O(n) time, O(1) space, in a single pass โ and it never mutates the input. Crucially, being single-pass means it also works on a stream you can't rewind, which the sort version can't claim.
14. Python Code
def maxProduct(nums: list[int]) -> int:
"""
LeetCode 1464 โ Maximum Product of Two Elements in an Array.
Returns the maximum value of (nums[i] - 1) * (nums[j] - 1)
over all pairs of distinct indices i != j.
One-pass top-two selection: O(n) time, O(1) space.
"""
first = 0 # largest value seen so far
second = 0 # second-largest value seen so far
# Seeding at 0 is safe only because every value is guaranteed >= 1.
for n in nums:
if n >= first:
# New champion: demote the old champion to runner-up.
second = first
first = n
elif n > second:
# Not a new champion, but beats the current runner-up.
second = n
return (first - 1) * (second - 1)
15. Code Walkthrough
Let's go line by line where it matters.
first = 0/second = 0โ We seed both registers to0. This is safe only because the problem promises every value is at least1; any real element will beat the seed. If negatives were allowed, we'd seed withfloat('-inf')instead.if n >= first:โ When the current number is a new maximum, we run the cascade:second = firstfirst, thenfirst = n. Doing the demotion first preserves the old champion as the new runner-up. The tuple-free two-step ordering here is deliberate; you could also writefirst, second = n, firstas an atomic swap-style assignment to avoid any temp-variable ordering bug.elif n > second:โ This branch is load-bearing. It catches values that don't beat the champion but do beat the runner-up. Note it's anelif, not a secondif. If it wereif, a single large value could fall through and fill both slots incorrectly.The
>=in the first comparison โ Using>=(not strict>) is what makes duplicates work. When a second equal maximum arrives,n >= firstis true, so the old max slides down intosecond. This is exactly why distinct indices, not distinct values is handled correctly.return (first - 1) * (second - 1)โ Apply the transform to the two largest and multiply.
16. Dry Run
Let's trace nums = [1, 5, 4, 5], the duplicate-maximum case, step by step.
| Step | n |
Branch taken | first | second |
|---|---|---|---|---|
| init | โ | โ | 0 | 0 |
| 1 | 1 | 1 >= 0 โ champion |
1 | 0 |
| 2 | 5 | 5 >= 1 โ champion |
5 | 1 |
| 3 | 4 | 4 > 1 โ runner-up |
5 | 4 |
| 4 | 5 | 5 >= 5 โ champion |
5 | 5 |
On step 4, the second 5 satisfies n >= first, so the old 5 is demoted into second. Both registers end at 5.
Result: (5 - 1) * (5 - 1) = 4 * 4 = 16. โ
Notice how the >= quietly handled the duplicate. A strict > on that first comparison would have skipped the update, leaving second = 4, and returned 12 โ wrong.
17. Complexity Analysis
| Approach | Time | Space | Notes |
|---|---|---|---|
| Brute force | O(nยฒ) |
O(1) |
Checks every pair |
| Sort | O(n log n) |
O(1)* |
Mutates input; overkill |
| One pass | O(n) |
O(1) |
Single pass, streamable |
* Space depends on the sort implementation; Python's Timsort can use O(n) in the worst case.
Why O(n) time? We touch each element exactly once, doing a constant amount of comparison and assignment per element. No nested loops, no re-scanning.
Why O(1) space? We store exactly two integers, first and second, regardless of input size. Nothing grows with n.
The one-pass version wins on every axis that matters: fewer operations, constant memory, and โ uniquely โ it works on a one-directional stream.
18. Alternative Solutions
Bounded heap (heapq.nlargest). Python's standard library gives you the top two directly:
import heapq
def maxProduct(nums: list[int]) -> int:
a, b = heapq.nlargest(2, nums)
return (a - 1) * (b - 1)
This is the cleanest readable answer and runs in O(n) for a fixed small K. It's also the pattern that generalizes: the moment an interviewer bumps the problem to "top K" or a streaming feed, a bounded heap of size K keeps you linear-ish (O(n log K)) with O(K) space. The manual two-register version is just the K=2 specialization of this idea โ worth recognizing that connection.
When to use which: For this exact problem, the hand-rolled one-pass is the fastest and most explicit. For top-K generalizations, reach for the heap.
19. Edge Cases
- Minimum length (
len == 2): e.g.[1, 1]. Both registers always fill, so the0seed never leaks into the answer. Returns0. - All ones (
[1, 1, 1]): Returns0. This is correct โ every factor is1 - 1 = 0. - Duplicate maximum (
[5, 5]): Handled by the>=comparison. Returns16. - Large values: Products can be large, but Python integers are unbounded, so there's no overflow concern.
- Values below 1: The problem forbids these. If they were allowed, the
0seed would be unsafe and you'd need-infseeds plus min-value tracking.
20. Common Mistakes
- Using a strict
>in the first comparison. This silently drops a duplicate maximum and returns the wrong product on inputs like[5, 5]. - Deduplicating with
set(). Wrapping the input in a set assumes distinct values. The problem only requires distinct indices, so[5, 5]collapses to[5]and breaks. - Writing
if ... if ...instead ofif ... elif .... Two independentifs can let a single large value overwrite both registers, leaking the true second-largest. - Forgetting the demotion. If you set
first = nwithout first sliding the old champion intosecond, you lose the runner-up entirely and get a wrong answer. - Seeding at
0while assuming general inputs. The0seed is only safe under the "values โฅ 1" guarantee. Reuse this template on a problem that allows non-positives, and it breaks quietly. - Sorting without flagging the cost. It works, but paying
O(n log n)โ and mutating the caller's array โ to learn two facts is worth calling out in an interview.
21. Interview Questions (Likely Follow-ups)
- "What if I ask for the top K largest, not just two?" โ Switch to a bounded min-heap of size K:
O(n log K)time,O(K)space. Your two-register solution is the K=2 case. - "What if the input is a stream you can't re-read?" โ The one-pass version already handles this; the sort version cannot.
- "What if negative numbers were allowed?" โ You'd also track the two smallest values and compare both candidate products, because two large negatives can multiply to a large positive.
- "Can you do it without mutating the input?" โ Yes โ the one-pass and
heapq.nlargestversions never touch the original array. - "Why is
O(n)optimal here?" โ You must inspect every element at least once to be sure you found the maximum, so you can't beat linear.
22. Similar Problems
- LeetCode 215 โ Kth Largest Element in an Array. The direct generalization: same order-statistics idea, larger K.
- LeetCode 628 โ Maximum Product of Three Numbers. Adds the negative-number twist, so you must track smallest values too โ a perfect contrast to why this problem stays simple.
- LeetCode 414 โ Third Maximum Number. Another fixed-register scan, extended to three slots with distinctness rules.
- LeetCode 1913 โ Maximum Product Difference Between Two Pairs. Needs both the two largest and two smallest in one pass.
Each of these reinforces the same core skill: partial selection over full sorting.
23. Key Takeaways
- Monotonicity is what licenses the top-two shortcut. Because
x - 1is increasing and values are non-negative, maximizing each factor independently maximizes the product. - The
elifand the demotion are the two lines that carry correctness. Break either and you leak the second-largest. - The
0seed is safe only under the non-negativity constraint. Know why, so you don't reuse it blindly. - Selection beats sorting when you only need a few order statistics.
O(n)and single-pass beatO(n log n). - This is top-K with K=2. Generalize it to a bounded heap and you get streaming top-K for free.
24. Watch the Video
Reading the reasoning is one thing โ watching the two registers cascade in real time makes it click. In the video I predict the tricky [2, 2] output before running it, race sorting against the one-pass scan, and stress-test every edge case live. Watch the full walkthrough here: {LINK}
25. About the Series
This is part of Fun with Learning Technology โ a series that treats coding problems as a way to build real intuition, not memorize patterns. Every episode rebuilds a problem from first principles: why the approach works, where it breaks, and how it connects to the bigger ideas in algorithms, data structures, and everyday software engineering. If you're preparing for a coding interview or just want to think more clearly about Python, you're in the right place.
26. Call To Action
If this made the problem click for you:
- ๐ Like the video on YouTube โ it genuinely helps the channel reach more developers.
- ๐ Subscribe so you catch tomorrow's drop, where this exact top-two pattern levels up into a harder heap problem.
- ๐ฉ Subscribe on Substack for the written breakdowns delivered to your inbox.
- ๐ฌ Comment with your guess for the
[2, 2]case โ or a problem you want covered next. - ๐ Share it with someone grinding through interview prep.
GITHUB README
# Maximum Product of Two Elements in an Array โ LeetCode 1464 (Python)
One-pass `O(n)` solution with full reasoning, dry runs, and edge cases.
## Problem
Given an array `nums`, choose two elements at **distinct indices** `i` and `j`
and maximize `(nums[i] - 1) * (nums[j] - 1)`. Return that maximum.
- Indices must differ; **values may repeat**.
- Every value is guaranteed `>= 1` (no zeros, no negatives).
## Intuition
Define `f(x) = x - 1`. On a non-negative domain, `f` is monotonically
increasing, and the product of two non-negative increasing terms is maximized
by maximizing each factor independently. Therefore the optimal pair is always
**the two largest values** in the array. Sorting or checking every pair is
wasted work โ we only need the 1st and 2nd order statistics.
> The non-negativity guarantee is essential: with negatives allowed, two large
> negative values could win, and you'd also track the two smallest.
## Approach
Single pass with two registers, `first` and `second`. When a new value beats
`first`, demote the old champion into `second` (the demotion is the whole
correctness argument). The `>=` comparison makes duplicate maxima work, which
is why *distinct indices, not values* holds.
## Python Solution
```python
def maxProduct(nums: list[int]) -> int:
first = 0 # largest so far
second = 0 # runner-up so far (0-seed safe because values >= 1)
for n in nums:
if n >= first:
second = first # demote old champion
first = n
elif n > second:
second = n
return (first - 1) * (second - 1)
Complexity
| Approach | Time | Space |
|---|---|---|
| Brute force | O(n^2) |
O(1) |
| Sort | O(n log n) |
O(1) |
| One pass | O(n) |
O(1) |
The one-pass version is also single-pass and streamable.
Edge Cases
[2, 2]โ1(duplicate maxima, distinct indices)[1, 1, 1]โ0(all minimum values โ correct, not a bug)- Length-2 input โ both registers always fill;
0-seed never leaks
Video
Full walkthrough: {LINK}
Article
Deep dive with dry runs, common mistakes, and top-K generalization: {LINK}
---
# SOCIAL MEDIA
## LinkedIn Post
Here's a LeetCode problem that looks trivial and quietly teaches something important about engineering judgment: **Maximum Product of Two Elements in an Array** (1464).
The task: pick two elements at different positions, subtract one from each, multiply, and maximize the result.
Most people's first move is to sort the array and read the last two values. It works. It's also `O(n log n)` โ and it mutates the caller's input. In an interview, that's the moment an interviewer learns how you think.
The better instinct: you don't need the array *in order*. You only need the two largest values. That's a single `O(n)` pass with two variables โ no sort, no extra memory, and it even works on a stream you can't rewind.
Why is "two largest" always correct? Because `x - 1` is monotonically increasing on this problem's non-negative domain, and the product of two non-negative increasing terms is maximized by maximizing each factor independently. That reasoning is the whole solution.
Two details that trip people up:
โข The problem says distinct *indices*, not distinct *values*. `[2, 2]` is valid and returns `1`.
โข Seeding your trackers at `0` is only safe because values are guaranteed `>= 1`.
The bigger lesson: this is just the K=2 case of top-K selection. Recognize that, and streaming top-K with a bounded heap comes for free.
Selecting a few values isn't the same as sorting all of them โ and knowing the difference is what interviews are really testing.
Full breakdown in the comments. #Python #CodingInterview #Algorithms #DataStructures
## Twitter/X Thread
**1/** LeetCode 1464 "Maximum Product of Two Elements" looks like a one-liner. It's actually a clean test of whether you know the difference between *sorting* and *selecting*. Let's break it down. ๐งต
**2/** The task: pick two elements at different positions, subtract 1 from each, multiply, maximize. That's it. So what's the catch?
**3/** First instinct: sort the array, take the last two. It works โ but it's O(n log n) and it mutates your input. You're paying to fully order the array just to learn TWO facts about it.
**4/** Key realization: you don't need the array in order. You only need the two largest values. That's the 1st and 2nd order statistics โ nothing else.
**5/** Why is "two largest" always optimal? f(x) = x - 1 is increasing on this non-negative domain. Product of two non-negative increasing terms โ maximize each factor independently โ grab the top two. Proven.
**6/** So: one pass, two variables. `first` = biggest so far, `second` = runner-up. When a new value beats `first`, demote the old champ into `second`. O(n) time, O(1) space.
**7/** That demotion line is the whole correctness argument. Skip it and you leak the second-largest. Classic off-by-one when people hand-roll this under pressure.
**8/** The trap: [2, 2]. Does it return 1 or break? It returns 1 โ because the problem wants distinct INDICES, not distinct VALUES. A `set()` dedup or a strict `>` silently breaks this.
**9/** Edge cases it survives: [1,1,1] โ 0 (correct, not a bug). Length-2 input โ both registers always fill, so the 0-seed never leaks. The only thing it can't handle: values below 1.
**10/** The real payoff: this is top-K with K=2. Generalize the two registers to a bounded heap and you've got streaming top-K for free. That's the follow-up interviewers love. Full walkthrough + video ๐
## Facebook Post
Quick one for anyone doing coding interview prep ๐
LeetCode's "Maximum Product of Two Elements in an Array" looks like a throwaway problem โ pick two numbers, subtract one from each, multiply, maximize. But it hides a genuinely useful lesson.
Most people sort the array and grab the last two. It works! But you don't actually need the whole thing sorted โ you only need the two biggest numbers, which you can find in a single sweep with two variables. Faster, uses no extra memory, and it even works on data you can only read once.
There's also a sneaky test case: `[2, 2]`. A lot of people assume it breaks, but it correctly returns `1`, because the problem lets you use two equal numbers as long as they sit in different positions.
I walk through the whole thing โ the intuition, the one-pass trick, and every edge case โ in the new video. Come learn the *why*, not just the answer. ๐
## Reddit Summary
**Maximum Product of Two Elements in an Array (LeetCode 1464) โ why the one-pass beats sorting, and the duplicate trap**
Sharing a breakdown in case it helps someone. The problem: pick two elements at distinct indices, compute `(a-1)*(b-1)`, maximize it.
The core insight is that `x - 1` is monotonically increasing on this problem's non-negative domain, so the product is maximized by just taking the two largest values โ no need to sort everything or check all pairs. That reduces it to finding the 1st and 2nd order statistics, which is a single O(n) pass with two variables (O(1) space, and it works on a stream).
Two things worth flagging:
- The constraint is distinct **indices**, not distinct **values**. So `[2, 2]` is valid and returns `1`. If you `set()` the input or use a strict `>` when checking against your max, you'll silently drop the duplicate.
- Seeding your two trackers at `0` only works because values are guaranteed `>= 1`. On a variant that allows negatives, you'd seed with `-inf` and also track the two smallest.
The neat part is recognizing this as the K=2 case of top-K selection โ swap the two registers for a bounded heap and you've generalized to streaming top-K.
Happy to discuss the negative-number variant (LeetCode 628 is the natural next step) if anyone wants to compare approaches.
The solution
def maxProduct(nums):
first = second = 0
for n in nums:
if n > first:
first, second = n, first
elif n > second:
second = n
return (first - 1) * (second - 1)Ready to try it yourself? Solve Stack problems with instant feedback in the practice sandbox.
Practice now โ


