๐ฌ Saturday Deep Dive: Maximum Product Subarray โ ไน็งฏๅญๆฐ็ป็ๅ่ฝจ DP (15 min read)
๐ NeetCode: 106/150 ยท SysDesign: 60/40 ยท Behavioral: 60/40 ยท Frontend: 37/50 ยท AI: 30/30
๐ฅ Day 137!
Overview / ๆฆ่ฟฐ
ไธญๆ๏ผ
Maximum Product Subarray๏ผLeetCode #152๏ผๆฏไธ้็ไผผ็ฎๅใๅฎๅๆ่ๆๆบ็ DP ้ขใๅฆๆไฝ ็จ Kadane ็ฎๆณ็ๆ่ทฏๅปๅไนๆณ็ๆฌ๏ผไฝ ไผๅจ่ดๆฐไธๆ่ทๅคดใๆ ธๅฟ้ฎ้ขๆฏ๏ผ่ดๆฐไนไปฅ่ดๆฐไผๅๆๆญฃๆฐโโ่ฟๆๅณ็"ๅฝๅๆๅฐๅผ"้ๆถๅฏ่ฝ็ฟป่บซๆไธบ"ๅฝๅๆๅคงๅผ"ใ
ๆฌๆๆทฑๅบฆ่งฃๆ๏ผ
- ไธบไปไนไน็งฏ DP ๅฟ ้กปๅๆถ่ฟฝ่ธช max ๅ min
- ๅฎๆด็็ถๆ่ฝฌ็งปๆจๅฏผ่ฟ็จ
- ไปๆดๅ O(nยฒ) ๅฐๆไผ O(n) ็่ฟๅ่ทฏๅพ
- ่ดๆฐใ้ถใๅ จ่ดๆฐๆฐ็ป็ญ 5 ็ง่พน็ๆ ๅต
- ่ฟไธช"ๅ่ฝจ่ฟฝ่ธช"ๆๅทงๅจๅ ถไป้ข็ฎไธ็ๅปถไผธ
English๏ผ
Maximum Product Subarray (#152) is deceptively tricky. If you naively apply Kadane's algorithm to multiplication, negatives will bite you. The core insight: a negative ร a negative = a positive, meaning today's minimum product could become tomorrow's maximum.
This deep dive covers:
- Why you must track both max and min simultaneously
- Full derivation of the state transition
- Evolution from brute force O(nยฒ) to optimal O(n)
- 5 edge cases that trip up candidates
- Where this "dual-track DP" pattern appears in other problems
๐ LeetCode: https://leetcode.com/problems/maximum-product-subarray/
๐น NeetCode: https://neetcode.io/problems/maximum-product-subarray
Part 1: Theory / ็่ฎบๅบ็ก (5 min)
ไธบไปไนๅ ๆณ DP ไธ่ฝ็ดๆฅ็จไบไนๆณ๏ผ/ Why Kadane's Doesn't Directly Transfer
ไธญๆ๏ผ
ๅ ๅๅฟ Kadane ็ฎๆณ๏ผๆๅคงๅญๆฐ็ปๅ๏ผ็ๆ ธๅฟๆๆณ๏ผ
max_ending_here = max(num, max_ending_here + num)
้ป่พๅพ็ฎๅ๏ผ่ฆไนไปๅฝๅๆฐ้ๆฐๅผๅง๏ผ่ฆไนๆๅฝๅๆฐๅ ๅฐไนๅ็ๆๅคงๅญๆฐ็ปไธใ
ไฝไนๆณๅฎๅ
จไธๅใ่่ๆฐ็ป [-2, -3, 7]๏ผ
- Kadane ๆ็ปด๏ผ-2 ไธบ่ด๏ผไธขๆ๏ผ-3 ไธบ่ด๏ผไธขๆ๏ผ็ญๆกๆฏ 7
- ๆญฃ็กฎ็ญๆก๏ผ(-2) ร (-3) ร 7 = 42
ไธบไปไน๏ผๅ ไธบไธคไธช่ดๆฐ็ธไนๅๆญฃๆฐ๏ผ่ไธไน็งฏ็็ปๅฏนๅผๅฏไปฅๅพๅคงใ
ๅ ณ้ฎๆจ่ฎบ๏ผๅจไนๆณ DP ไธญ๏ผๆไปฌๅฟ ้กปๅๆถ็ปดๆคไธคไธช็ถๆโโไปฅ i ็ปๅฐพ็ๅญๆฐ็ป็ๆๅคงไน็งฏ๏ผmax_prod๏ผๅๆๅฐไน็งฏ๏ผmin_prod๏ผใ
English๏ผ
Recall Kadane's core idea (maximum subarray sum):
max_ending_here = max(num, max_ending_here + num)
Simple logic: either restart from current element, or extend the previous best subarray.
With multiplication, consider [-2, -3, 7]:
- Kadane thinking: -2 is negative, discard; -3 is negative, discard; answer = 7
- Correct answer: (-2) ร (-3) ร 7 = 42
Why? Two negatives multiply to a positive, potentially huge. The key corollary: in product DP, we must maintain both max_prod and min_prod ending at position i.
็ถๆๅฎไน / State Definition
ไธญๆ๏ผ
max_prod[i] = ไปฅ nums[i] ็ปๅฐพ็ๆๆๅญๆฐ็ปไธญไน็งฏๆๅคง็ๅผ
min_prod[i] = ไปฅ nums[i] ็ปๅฐพ็ๆๆๅญๆฐ็ปไธญไน็งฏๆๅฐ็ๅผ
็ถๆ่ฝฌ็งปๆน็จ๏ผ3 ็งๅ้๏ผ๏ผ
ไปฅ nums[i] ็ปๅฐพ็ๅญๆฐ็ป๏ผๅชๆ 3 ็งๆ
ๅต๏ผ
1. ไป
ๅ
ๅซ nums[i] ๆฌ่บซ
2. nums[i] ร max_prod[i-1] ๏ผๆฉๅฑไนๅ็ๆๅคงไน็งฏ๏ผ
3. nums[i] ร min_prod[i-1] ๏ผๆฉๅฑไนๅ็ๆๅฐไน็งฏ๏ผ
ๅฝ nums[i] > 0 ๆถ๏ผๆ
ๅต2้ๅธธไบง็ๆฐๆๅคงๅผ
ๅฝ nums[i] < 0 ๆถ๏ผๆ
ๅต3ๅฏ่ฝ็ฟป่ฝฌๆๆฐๆๅคงๅผ๏ผ่ด ร ่ด = ๆญฃ๏ผ๏ผ
ๅฝ nums[i] = 0 ๆถ๏ผ3็งๅ้้ฝๅฝ้ถ๏ผ้ๆฐๅผๅง
ๅ ๆญค๏ผ
max_prod[i] = max(nums[i], nums[i] ร max_prod[i-1], nums[i] ร min_prod[i-1])
min_prod[i] = min(nums[i], nums[i] ร max_prod[i-1], nums[i] ร min_prod[i-1])
English๏ผ
max_prod[i] = maximum product of any subarray ending at nums[i]
min_prod[i] = minimum product of any subarray ending at nums[i]
State transition โ 3 candidates at each position:
Subarrays ending at nums[i] fall into exactly 3 cases:
1. Just nums[i] alone
2. nums[i] ร max_prod[i-1] (extend previous max)
3. nums[i] ร min_prod[i-1] (extend previous min)
When nums[i] > 0: case 2 likely gives the new max
When nums[i] < 0: case 3 might flip to new max (negative ร negative = positive!)
When nums[i] = 0: all candidates are 0; reset
Therefore:
max_prod[i] = max(nums[i], nums[i] ร max_prod[i-1], nums[i] ร min_prod[i-1])
min_prod[i] = min(nums[i], nums[i] ร max_prod[i-1], nums[i] ร min_prod[i-1])
็ด่งๅพ / Intuition Diagram
Part 2: Step-by-Step Implementation / ไธๆญฅไธๆญฅๅฎ็ฐ (8 min)
Approach 1: Naive Brute Force โ O(nยฒ)
ไธญๆ๏ผๆดๅ่งฃๆณ๏ผๆไธพๆๆๅญๆฐ็ปใ้ข่ฏๆถๅฑ็คบ"ๆ็ฅ้ๆดไผ่งฃ๏ผๅ ็ปๅบๅ"ใ
English: Brute force โ enumerate all subarrays. Show this first to establish baseline.
def maxProduct_brute(nums: list[int]) -> int:
"""
Brute force: try every possible subarray [i..j]
Time: O(n^2), Space: O(1)
"""
n = len(nums)
result = nums[0]
for i in range(n):
product = 1
for j in range(i, n):
product *= nums[j] # extend subarray [i..j]
result = max(result, product) # update global max
return result
# Test: [2, 3, -2, 4] โ 6 (subarray [2,3])
print(maxProduct_brute([2, 3, -2, 4])) # 6 โ
print(maxProduct_brute([-2, 0, -1])) # 0 โ
print(maxProduct_brute([-2, 3, -4])) # 24 โ
Approach 2: Optimal Dual-Track DP โ O(n) time, O(1) space
def maxProduct(nums: list[int]) -> int:
"""
Dual-track DP: track both max and min product ending at current position.
Key insight: when nums[i] is negative, multiply by min_prod (which is
also negative) gives a large positive โ the new max.
Time: O(n), Space: O(1)
"""
if not nums:
return 0
# Initialize: both max and min start as nums[0]
max_prod = nums[0] # max product of subarray ending here
min_prod = nums[0] # min product of subarray ending here
result = nums[0] # global maximum found so far
for i in range(1, len(nums)):
n = nums[i]
# --- CRITICAL: compute candidates BEFORE overwriting max_prod/min_prod ---
# Three possible products for subarrays ending at index i:
candidate1 = n # start fresh: just [nums[i]]
candidate2 = n * max_prod # extend previous max subarray
candidate3 = n * min_prod # extend previous min subarray
# New max is the largest of the three
max_prod = max(candidate1, candidate2, candidate3)
# New min is the smallest (track for future negative multiplications)
min_prod = min(candidate1, candidate2, candidate3)
# Update global result
result = max(result, max_prod)
return result
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Trace through [2, 3, -2, 4]:
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Start: max_prod=2, min_prod=2, result=2
#
# i=1, n=3:
# candidates = (3, 3*2=6, 3*2=6)
# max_prod=6, min_prod=3, result=6
#
# i=2, n=-2:
# candidates = (-2, -2*6=-12, -2*3=-6)
# max_prod=-2, min_prod=-12, result=6
#
# i=3, n=4:
# candidates = (4, 4*(-2)=-8, 4*(-12)=-48)
# max_prod=4, min_prod=-48, result=6
#
# Final: 6 โ (subarray [2,3])
Full Walkthrough with State Table / ๅฎๆด็ถๆ่กจ
def maxProduct_verbose(nums: list[int]) -> int:
"""Same algorithm with step-by-step logging for understanding."""
max_prod = min_prod = result = nums[0]
print(f"Init: max={max_prod}, min={min_prod}, result={result}")
for i in range(1, len(nums)):
n = nums[i]
# Must save before overwriting!
prev_max, prev_min = max_prod, min_prod
max_prod = max(n, n * prev_max, n * prev_min)
min_prod = min(n, n * prev_max, n * prev_min)
result = max(result, max_prod)
print(f"i={i}, n={n}: "
f"candidates=({n}, {n*prev_max}, {n*prev_min}) "
f"โ max={max_prod}, min={min_prod}, result={result}")
return result
# Output for [-2, 3, -4]:
# Init: max=-2, min=-2, result=-2
# i=1, n=3: candidates=(3, -6, -6) โ max=3, min=-6, result=3
# i=2, n=-4: candidates=(-4, -12, 24) โ max=24, min=-12, result=24
# Answer: 24 โ
One-Liner Trick (Pythonic) / ไธ่กๆๅทง
ไธญๆ๏ผๅฏไปฅ็จ min() ๅ max() ็ปๅๆๆด็ฎๆด็ๅๆณ๏ผ
English: A compact version using tuple unpacking:
def maxProduct_compact(nums: list[int]) -> int:
max_p = min_p = result = nums[0]
for n in nums[1:]:
# Python evaluates the ENTIRE right-hand tuple BEFORE any assignment,
# so both max() and min() see the original (old) max_p and min_p. โ
max_p, min_p = (
max(n, n * max_p, n * min_p),
min(n, n * max_p, n * min_p)
)
result = max(result, max_p)
return result
# ๐ก Python tuple assignment is safe here: the RHS is fully evaluated first.
# max_p and min_p on the right still refer to the OLD values.
# If you prefer explicit clarity, save old values first:
# Safer (more readable) pattern:
def maxProduct_safe(nums: list[int]) -> int:
max_p = min_p = result = nums[0]
for n in nums[1:]:
# Save originals explicitly
old_max, old_min = max_p, min_p
max_p = max(n, n * old_max, n * old_min)
min_p = min(n, n * old_max, n * old_min)
result = max(result, max_p)
return result
Cross-Check: Diagram โ Code Trace / ไบคๅ้ช่ฏ
Pick input: [-2, 3, -4]
Code trace (using maxProduct_safe):
- Init:
max_p=-2, min_p=-2, result=-2 n=3:old_max=-2, old_min=-2โmax_p=max(3,-6,-6)=3,min_p=min(3,-6,-6)=-6,result=3n=-4:old_max=3, old_min=-6โmax_p=max(-4,-12,24)=24,min_p=min(-4,-12,24)=-12,result=24- Return 24 โ
Diagram matches code exactly. The min_prod=-6 tracked at i=1 is used at i=2 (-6 ร -4 = 24) โ matching the diagram's "HERO" path. โ
Part 3: Edge Cases & Gotchas / ่พน็ๆ ๅต (2 min)
ไธญๆ๏ผ5 ไธชๅฟ ้กปๆต่ฏ็่พน็ๆ ๅต๏ผ
English: 5 edge cases every interviewer expects you to handle:
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Case 1: Single element (including negative)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
assert maxProduct_safe([-3]) == -3 # Can't avoid it; must take it
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Case 2: Contains zero โ resets the product chain
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
assert maxProduct_safe([-2, 0, -1]) == 0 # Zero breaks both sides
# Why: [-2,0] = 0, [0,-1] = 0, [-2,0,-1] = 0 โ best is 0
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Case 3: All negative (even count) โ product is positive
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
assert maxProduct_safe([-2, -3, -4]) == 12 # (-2)ร(-3)ร(-4)... nope
# Wait: best subarray is [-2,-3]โ6 or [-3,-4]โ12 โ answer is 12 โ
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Case 4: All negative (odd count) โ forced to leave one out
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
assert maxProduct_safe([-2, -3, -4, -5]) == 120 # All four: (-2)ร(-3)ร(-4)ร(-5) = 120
# Even count of negatives โ full array product is positive. Answer: 120
assert maxProduct_safe([-2, -3, -4]) == 12 # Odd count โ skip one end
# Best: skip -2 โ (-3)ร(-4)=12, or skip -4 โ (-2)ร(-3)=6 โ answer 12
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Case 5: Multiple zeros splitting the array
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
assert maxProduct_safe([0, 2, 0, -5, 0]) == 2 # Each segment independent
้ข่ฏๆณจๆ็น / Interview Gotchas:
| ๆ ๅต | ๅๅ | ๅค็ๆนๅผ |
|---|---|---|
| ้ๅฐ 0 | ไน็งฏๅฝ้ถ๏ผไนๅ็ๅญๆฐ็ป็ฌ็ซ่ฎก็ฎ | ๅ้1๏ผไป nums[i]๏ผ=0๏ผ่ช็ถ้็ฝฎ |
| ๅ จ่ดๅถๆฐไธช | ๅ จ้จ็ธไนๆไผ | ็ฎๆณ่ชๅจๅค็ |
| ๅ จ่ดๅฅๆฐไธช | ๅปๆ็ปๅฏนๅผๆๅฐ็็ซฏ็น | ็ฎๆณ่ชๅจๅค็ |
| ๅๅ ็ด | ๅฟ ้กป่ฟๅ่ฏฅๅ ็ด ๏ผๅณไฝฟไธบ่ด๏ผ | ๅๅงๅไธบnums[0] |
| ๅ้่ฎก็ฎ้กบๅบ | ๅฟ ้กป็จไธไธ่ฝฎ็max/min | ๅ ไฟๅญ old_max, old_min |
Part 4: Real-World Application / ๅฎ้ ๅบ็จ (2 min)
ไธญๆ๏ผ
่ฟ้้ข็ๆ ธๅฟๆๅทงโโๅๆถ่ฟฝ่ธชๆๅคงๅผๅๆๅฐๅผโโๅจ็ไบง็ฏๅขไธญๆ็ๅฎ็็ฑปๆฏๅบๆฏ๏ผ
1. ้่้ฃ้ฉ่ฎก็ฎ๏ผ
ไธ็ณปๅไนๆณๆถ็็๏ผๅฆ +10%, -20%, +30%๏ผไธญ๏ผๆพๆไผๆไป็ชๅฃใ่ดๆถ็ๅฏ่ฝ"ๆๆดป"ๅฆไธๆฎต่ดๆถ็ๆ๏ผ็ฉบๅคดไปไฝ๏ผใ่ฟฝ่ธชๆๅคงๆฝๅจๆถ็ๅๆๅคงๆฝๅจๆๅคฑๅๆ ท้่ฆใ
2. ๅฏนๆฐ่ฝฌๆข โ ๅ ๆณ๏ผ
ๅจๅฎ้ ็ณป็ปไธญ๏ผ่ฟ็ปญไน็งฏๅธธ็จๅฏนๆฐ่ฝฌๅไธบๅ ๆณ๏ผ้ฟๅ ไธๆบข/ไธๆบข๏ผ๏ผ
import math
# Max product of subarray โก max sum of log(|nums[i]|)
# ไฝ่ฆๅค็่ดๆฐ็็ฌฆๅท้ฎ้ข โ ้่ฆ็นๆฎๆ ่ฎฐ
3. NLP/ML ๅบๅ่ฏๅ๏ผ
่ฏญ่จๆจกๅ่ฎก็ฎๅฅๅญๆฆ็ๆฏๅ่ฏๆฆ็็่ฟไน็งฏใๆพ"ๆ้ซ็ฝฎไฟกๅบฆๅญๅบๅ"ๆฌ่ดจไธๆฏๅ็ง็ Maximum Product Subarrayใ
English:
The dual-track technique appears in real systems:
1. Financial returns: A series of multiplicative returns (+10%, -20%, +30%) โ find the optimal holding window. Short positions mean negative returns can compound positively.
2. Log-space arithmetic: Production ML systems compute log-probabilities (sums) instead of raw products to avoid underflow. But the sign-tracking problem remains.
3. Sequence scoring: Finding the highest-confidence span in an NLP model's token probability sequence is exactly this pattern.
The abstract pattern (generalize this!):
"When the 'worst' state can become the 'best' state due to the nature of the operation, you must track both extremes."
This appears in: Maximum Product Subarray, Maximum Absolute Sum of Subarray (#1749), products with complex numbers, etc.
Part 5: Interview Simulation / ้ข่ฏๆจกๆ (3 min)
ๅบๆฏ๏ผไฝ ๅจ Meta E5 ้ข่ฏ๏ผ้ข็ฎๆฏ #152
Q1: ้ข่ฏๅฎ้ฎ๏ผไธบไปไน่ฆ่ฟฝ่ธช min_prod๏ผไธๅฐฑๆฏ่ฟฝ่ธชๆๅคง็ๅฐฑๅฅฝไบ๏ผ
A: ไธๅคใไนๆณๆ"็ฟป่ฝฌ"ๆๅบ๏ผๅฝๅ็ๆๅฐไน็งฏ๏ผ่ดๆฐ๏ผไนไปฅไธไธไธช่ดๆฐ๏ผไผๅๆๆๅคงไน็งฏใๅฆๆๅช่ฟฝ่ธช max_prod๏ผไฝ ไผ้่ฟ่ฟไธช็ฟป่ฝฌๆบไผใ
ไพๅญ๏ผ[-5, -3] โ ไป
่ฟฝ่ธช max ็่ฏ๏ผmax_prod[-5]=-5๏ผๅฐ -3 ๆถ๏ผๅ้ๆฏ๏ผ-3, -3ร(-5)=15, -3ร(-5)=15๏ผโ max=15ใ่ฟ้ๆฐๅฅฝ่ฟๆฏๅฏน็๏ผไฝๅจๆดๅคๆ็ๅบๅไธญไฝ ้่ฆ min ๆฅ้ฟๅ
้่ฟๆทฑๅฑ็ฟป่ฝฌใ
Q2: ่ฟไธช็ฎๆณๅค็ๅ จ้ถๆฐ็ปๆญฃ็กฎๅ๏ผ
A: ๆฏ็ใๅ
จ้ถๆฐ็ป [0, 0, 0]๏ผๅๅงๅ result=0๏ผๆฏๆญฅไธไธชๅ้้ฝๆฏ 0๏ผๆ็ป่ฟๅ 0ใๆญฃ็กฎใ
Q3: ๅฆๆ้ข็ฎๆนๆ"ๆๅฐไน็งฏๅญๆฐ็ป"ๆไนๆน๏ผ
A: ๅช้ๆresult = max(result, max_prod)ๆนๆresult = min(result, min_prod)๏ผๅ ถไฝ้ป่พๅฎๅ จ็ธๅใmin_prod ๅทฒ็ปๅจ่ฟฝ่ธชไบใ
Q4: ่ฝ็จ Divide and Conquer ่งฃ่ฟ้้ขๅ๏ผๆถ้ดๅคๆๅบฆๅคๅฐ๏ผ
A: ๅฏไปฅ๏ผ็ฑปไผผ Maximum Subarray ็ๅๆฒป่งฃๆณใๆฏๆฌกไปไธญ็นๅๅฒ๏ผ็ญๆกๆฏไปฅไธไธ่ ไนไธ๏ผๅทฆๅ้จๅ็ๆๅคงไน็งฏใๅณๅ้จๅ็ๆๅคงไน็งฏใๆ่ทจ่ถไธญ็น็ๆๅคงไน็งฏใ่ทจ่ถไธญ็น็่ฎก็ฎ้่ฆไปไธญ็นๅไธคไพงๆฉๅฑ๏ผไฝไนๆณ็ๆฌ้่ฆๅๆถ็ปดๆคๆๅคงๅๆๅฐ๏ผๅคๆๅบฆ O(n log n)ใไธๅฆ็บฟๆง DP๏ผ้ๅธธๆฒกๅฟ ่ฆๆ๏ผไฝไฝ็ฐไบๅๆฒปๆ็ปดใ
Q5: ๅฆๆๆฐ็ป้ๅธธๅคง๏ผ10ไบฟๅ ็ด ๏ผ๏ผๅฆไฝๅนถ่กๅ๏ผ
A: ่ฟๆฏ็ณป็ป่ฎพ่ฎกๅปถไผธใๅฏไปฅๅๅๅนถ่ก๏ผๆฏๅ่ฟๅ (max_prod, min_prod, prefix_max, prefix_min, suffix_max, suffix_min, total_product)๏ผ็ถๅๅๅนถใ็ฑปไผผ segment tree ็ๆ่ทฏ๏ผ้ๅ MapReduce ๆ Sparkใๅๅนถ้ป่พๆฏ่ฟ้้ข็ถๆ่ฝฌ็งปๆน็จ็"ๅๅธๅผ็ๆฌ"ใ
Summary / ๆป็ป
ไธญๆ๏ผ
| ็ปดๅบฆ | ่ฆ็น |
|---|---|
| ๆ ธๅฟๆดๅฏ | ่ด ร ่ด = ๆญฃ๏ผๅฟ ้กปๅๆถ่ฟฝ่ธช max ๅ min |
| ็ถๆ | max_prod[i], min_prod[i]๏ผ็ฉบ้ดไผๅไธบ O(1) |
| ่ฝฌ็งปๆน็จ | max(n, nรprev_max, nรprev_min) |
| ้ถ็ๅค็ | ๅ้1๏ผไป nๆฌ่บซ๏ผ่ชๅจๅค็้็ฝฎ |
| ๆถ้ดๅคๆๅบฆ | O(n) |
| ้ข่ฏๆๅทง | ๅ ๅฑ็คบๆดๅ่งฃ๏ผๅๆจๅฏผๅ่ฝจ DP๏ผ็จๅ ทไฝไพๅญ่ฏดๆไธบไฝ้่ฆ min_prod |
English:
| Dimension | Key Point |
|---|---|
| Core Insight | Negative ร negative = positive; track both max AND min |
| State | max_prod[i], min_prod[i]; space-optimize to O(1) |
| Recurrence | max(n, nรprev_max, nรprev_min) |
| Zero handling | Candidate 1 (just n) auto-resets the chain |
| Time Complexity | O(n) |
| Interview tip | Show brute force first, derive dual-track DP, use [-2,3,-4] to motivate why min_prod matters |
ๅปถไผธ็ปไน / Related Problems:
- #53 Maximum Subarray (ๅ ๆณ็๏ผKadane ็ปๅ ธ)
- #1749 Maximum Absolute Sum of Any Subarray (่ฟฝ่ธช็ปๅฏนๅผ็ๆๅคงๅๆๅฐ)
- #628 Maximum Product of Three Numbers (ไธๅ ็ด ๏ผๆๅบ่ดชๅฟ)
- #238 Product of Array Except Self (ๅ็ผ/ๅ็ผไน็งฏ)
byte-by-byte Day 137 โ Saturday Deep Dive
Generated: 2026-09-26