Maximumsubarray en maximumproductsubarray
Pas Kadane's algoritme toe op maximum-sum-subarray en breid het uit door zowel het maximum als het minimum bij te houden voor de productvariant.
Maximumsubarray en maximumproductsubarray is een gratis Voorbereiding op programmeerinterviews-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Voorbereiding op programmeerinterviews. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.
Probleem van de deelarray met maximale som
Het probleem van de maximale deelarray vraagt je om de aaneengesloten deelarray binnen een eendimensionale array met getallen te vinden die de grootste som heeft. In [-2, 1, -3, 4, -1, 2, 1, -5, 4] levert de deelarray [4, -1, 2, 1] bijvoorbeeld de maximale som van 6 op. Een brute-forcebenadering in O(n²) controleert alle deelarrays, maar het algoritme van Kadane lost dit op in O(n).
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
# Brute force: O(n^2)
max_sum = float('-inf')
for i in range(len(nums)):
curr = 0
for j in range(i, len(nums)):
curr += nums[j]
max_sum = max(max_sum, curr)
print(max_sum) # 6Intuïtie achter het algoritme van Kadane
Het algoritme van Kadane doorloopt de array één keer en houdt een lopende current_sum bij. Bij elk element bepaal je wat beter is: de bestaande deelarray uitbreiden of opnieuw beginnen met dit element? Als current_sum negatief wordt, zou dat elke toekomstige deelarray alleen maar schaden, dus begin je opnieuw. De recurrentie is current_sum = max(num, current_sum + num).
def max_subarray(nums):
max_sum = current_sum = nums[0]
for num in nums[1:]:
# Extend or start fresh?
current_sum = max(num, current_sum + num)
max_sum = max(max_sum, current_sum)
return max_sum
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
print(max_subarray(nums)) # 6Het algoritme van Kadane stap voor stap volgen
Laten we Kadane stap voor stap volgen op [-2, 1, -3, 4, -1, 2, 1, -5, 4]: begin met curr=-2, max=-2. Bij 1: curr=max(1,-2+1)=1, max=1. Bij -3: curr=max(-3,1-3)=-2, max=1. Bij 4: curr=max(4,-2+4)=4, max=4. Bij -1: curr=3, max=4. Bij 2: curr=5, max=5. Bij 1: curr=6, max=6. Bij -5: curr=1. Bij 4: curr=5, max=6. Het algoritme identificeert correct de deelarray die eindigt op index 6 als de optimale deelarray.
def max_subarray_trace(nums):
curr = max_sum = nums[0]
for i, num in enumerate(nums[1:], 1):
new_curr = max(num, curr + num)
max_sum = max(max_sum, new_curr)
print(f'i={i}, num={num}, curr: {curr}->{new_curr}, max={max_sum}')
curr = new_curr
return max_sum
max_subarray_trace([-2, 1, -3, 4, -1, 2, 1, -5, 4])De daadwerkelijke deelarray teruggeven
Als de interviewer je vraagt om de deelarray zelf terug te geven en niet alleen de som, moet je de begin- en eindindex bijhouden. Wanneer je opnieuw begint omdat num > current_sum + num, werk je een temp_start bij. Wanneer je max_sum bijwerkt, sla je temp_start op als start en de huidige index als end. Dit voegt O(1) overhead toe aan hetzelfde O(n)-algoritme.
def max_subarray_indices(nums):
max_sum = curr = nums[0]
start = end = temp_start = 0
for i in range(1, len(nums)):
if nums[i] > curr + nums[i]:
curr = nums[i]
temp_start = i
else:
curr += nums[i]
if curr > max_sum:
max_sum = curr
start, end = temp_start, i
return max_sum, nums[start:end+1]
print(max_subarray_indices([-2, 1, -3, 4, -1, 2, 1, -5, 4]))
# (6, [4, -1, 2, 1])Probleem van de deelarray met maximaal product
Het probleem van de deelarray met maximaal product is lastiger dan de variant met som vanwege negatieve getallen. Twee negatieve getallen leveren bij vermenigvuldiging een positief getal op, dus een zeer negatief product kan het maximum worden nadat het met nog een negatief getal is vermenigvuldigd. Voor [2, 3, -2, 4] is het antwoord 6 ([2, 3]). Voor [-2, 0, -1] is het antwoord 0. We moeten bij elke stap zowel de maximale als minimale producten bijhouden.
nums = [2, 3, -2, 4]
# [2,3,-2,4]: products [2, 6, -12, -48]
# subarrays: [2]=2, [2,3]=6, [3]=3, etc.
# max is 6 from subarray [2,3]
nums2 = [-2, 3, -4]
# [-2]*3*[-4] = 24
# negative*negative=positive!
print('Expected:', 24)Zowel maximale als minimale producten bijhouden
Het belangrijkste inzicht: op elke positie is het huidige maximale product een van num, max_so_far * num of min_so_far * num. Die laatste mogelijkheid is nuttig wanneer een negatief getal het minimum in een maximum omkeert. Hetzelfde geldt voor het minimum. Werk beide cur_max en cur_min gelijktijdig bij met de vorige waarden, zodat je in dezelfde stap geen al bijgewerkte waarden gebruikt.
def max_product(nums):
max_prod = min_prod = result = nums[0]
for num in nums[1:]:
# All three candidates for new max
candidates = (num, max_prod * num, min_prod * num)
max_prod, min_prod = max(candidates), min(candidates)
result = max(result, max_prod)
return result
print(max_product([2, 3, -2, 4])) # 6
print(max_product([-2, 3, -4])) # 24
print(max_product([-2, 0, -1])) # 0
print(max_product([-2])) # -2Waarom min_prod belangrijk is
Neem [-3, -10, 5]. Na het verwerken van -3: max=-3, min=-3. Na -10: de kandidaten zijn (-10, 30, 30) → max=30, min=-10. Na 5: de kandidaten zijn (5, 150, -50) → max=150. Zonder min_prod bij te houden, zou je de omkering missen die optreedt wanneer een sterk negatief minimum met nog een negatief getal wordt vermenigvuldigd. Bereken altijd zowel max als min op basis van dezelfde vorige waarden om een bug door het lezen van verouderde waarden te voorkomen.
def max_product_traced(nums):
max_p = min_p = result = nums[0]
for num in nums[1:]:
prev_max, prev_min = max_p, min_p
max_p = max(num, prev_max * num, prev_min * num)
min_p = min(num, prev_max * num, prev_min * num)
result = max(result, max_p)
print(f'num={num}: max_p={max_p}, min_p={min_p}')
return result
max_product_traced([-3, -10, 5])
# max_p after -10: 30 (flip!)
# max_p after 5: 150Nulwaarden zetten het product terug
Een nul in de array zet beide lopende producten terug op nul en splitst de array daardoor effectief op in onafhankelijke deelarrays. Wanneer num = 0, geldt zowel max_prod * 0 = 0 als min_prod * 0 = 0. Alle drie de kandidaten worden dus 0 en het vorige resultaat voor het maximum blijft behouden. Er is geen speciale code nodig — de algemene formule verwerkt nullen vanzelf.
def max_product(nums):
max_p = min_p = result = nums[0]
for num in nums[1:]:
cands = (num, max_p * num, min_p * num)
max_p, min_p = max(cands), min(cands)
result = max(result, max_p)
return result
# Zero splits array into independent subarrays
print(max_product([3, -1, 4, 0, 2, 5, -1])) # 10 (2*5)
print(max_product([0, 2])) # 2
print(max_product([-1, 0, -2])) # 0Alternatief: productscan van links naar rechts en van rechts naar links
Een alternatieve aanpak doorloopt de array van links naar rechts en van rechts naar links en zet het lopende product terug op 1 wanneer het een nul tegenkomt. De deelarray met maximaal product loopt nooit over een nul heen. Als een negatief getal de situatie in één richting verslechtert, vangt de omgekeerde scan de omkering op. Deze aanpak is elegant, maar de methode waarbij je het minimum en maximum bijhoudt wordt tijdens sollicitatiegesprekken vaker verwacht.
def max_product_sweep(nums):
result = max(nums)
left = right = 1
n = len(nums)
for i in range(n):
left *= nums[i]
right *= nums[n - 1 - i]
result = max(result, left, right)
if left == 0: left = 1
if right == 0: right = 1
return result
print(max_product_sweep([2, 3, -2, 4])) # 6
print(max_product_sweep([-2, 3, -4])) # 24
print(max_product_sweep([-2, 0, -1])) # 0Kadane versus product: belangrijkste verschillen
Deelarrays met een som en deelarrays met een product verschillen op belangrijke punten. Bij een som zijn negatieve getallen altijd schadelijk, dus begin je hebzuchtig opnieuw. Bij een product helpen twee negatieve getallen, dus moet je beide uitersten bijhouden. Bovendien beëindigen nullen productberekeningen, terwijl ze voor sommen slechts beperkt schadelijk zijn. Benoem deze verschillen tijdens een sollicitatiegesprek expliciet en leg uit waarom het nodig is om het minimum bij te houden voordat je code schrijft.
# Max Sum Subarray: O(n) time, O(1) space
def max_sum(nums):
curr = result = nums[0]
for n in nums[1:]:
curr = max(n, curr + n) # restart or extend
result = max(result, curr)
return result
# Max Product Subarray: O(n) time, O(1) space
def max_prod(nums):
lo = hi = result = nums[0]
for n in nums[1:]:
lo, hi = min(n, lo*n, hi*n), max(n, lo*n, hi*n)
result = max(result, hi)
return result
print(max_sum([-2, 1, -3, 4, -1, 2, 1])) # 6
print(max_prod([-2, 3, -4])) # 24Complexiteit en tips voor sollicitatiegesprekken
Zowel het algoritme van Kadane voor de maximale som als het bijhouden van minimum en maximum voor het maximale product werkt in O(n)-tijd en gebruikt O(1) ruimte. Belangrijke tips voor sollicitatiegesprekken: (1) Noem bij de maximale som het verdeel-en-heersalternatief in O(n log n) om je brede kennis te laten zien. (2) Benadruk bij het maximale product dat je min_prod en max_prod gelijktijdig bijwerkt op basis van vorige waarden, zodat je geen verouderde gegevens gebruikt. (3) Verduidelijk altijd: mag de array leeg zijn? Moet de deelarray niet-leeg zijn? (Ja, volgens de conventie moet die niet-leeg zijn.)
# Both run O(n) time, O(1) space
# Kadane handles: all negative (returns least negative)
# Product handles: zeros (resets naturally), negatives (tracks both extremes)
nums_all_neg = [-5, -2, -8]
print('Max sum (all neg):', max(max(nums_all_neg[0:1]),
max(x for x in nums_all_neg))) # -2
# Correct: return the maximum element when all are negativeKorte kennischeck
Test je begrip van de concepten van Data Structures & Algorithms — Coding Interview Prep uit deze les.
Samenvatting van de les
In deze les heb je geleerd: het algoritme van Kadane lost de deelarray met maximale som op in O(n) door bij elk element te kiezen tussen uitbreiden en opnieuw beginnen, voor de deelarray met maximaal product moet je zowel de minimale als maximale lopende producten bijhouden vanwege omkeringen door negatieve getallen en nullen zetten het lopende product vanzelf terug zonder speciale code. Vervolgens bekijken we het probleem van de woordafbreking met een eendimensionale dp-tabel.
Leer Voorbereiding op programmeerinterviews met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 90
- Lessen
- 360
Veelgestelde vragen
Is de les “Maximumsubarray en maximumproductsubarray” gratis?
Ja — de volledige tekst van “Maximumsubarray en maximumproductsubarray” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Voorbereiding op programmeerinterviews wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Voorbereiding op programmeerinterviews bevat in totaal 4 lessen.
Wat leer ik in “Maximumsubarray en maximumproductsubarray”?
Pas Kadane's algoritme toe op maximum-sum-subarray en breid het uit door zowel het maximum als het minimum bij te houden voor de productvariant. Je oefent met Voorbereiding op programmeerinterviews door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Voorbereiding op programmeerinterviews te beginnen?
Ervaring vooraf is niet nodig. Voorbereiding op programmeerinterviews op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Maximumsubarray en maximumproductsubarray”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Voorbereiding op programmeerinterviews?
Ja. Elke les over Voorbereiding op programmeerinterviews bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- House Robber: recurrentie voor nemen of overslaan
- Maximumsubarray en maximumproductsubarray
- Word Break en strings segmenteren
- Decode Ways en paden tellen