LeetCode 224, Basic Calculator, vraagt je een string met cijfers, +, -, haakjes en spaties te evalueren zonder eval te gebruiken. Er is geen vermenigvuldiging of deling, dus je hoeft geen operatorprioriteit te regelen. De enige moeilijkheid zijn de haakjes, en een stack met opgeslagen toestanden lost dat netjes op in één pass.
Het probleem
Gegeven een string s die een expressie voorstelt met niet-negatieve gehele getallen, +, -, (, ) en spaties, geef de waarde terug. Het minteken kan ook een unaire operator zijn, zoals in -(2 + 3).
Voorbeelden:
| Invoer | Uitvoer |
|---|---|
| "1 + 1" | 2 |
| " 2-1 + 2 " | 3 |
| "(1+(4+5+2)-3)+(6+8)" | 23 |
| "-(3 + (4 + 5))" | -12 |
Het kernidee
Scan van links naar rechts en houd drie dingen bij: het lopende resultaat, het huidige teken en het getal dat je opbouwt. Wanneer je een ( tegenkomt, begin je aan een subexpressie. Sla het resultaat en het teken vóór het haakje op een stack op, en begin opnieuw met resultaat 0 en teken +1. Wanneer je een ) tegenkomt, rond je de subexpressie af, vermenigvuldig je die met het opgeslagen teken en tel je die op bij het opgeslagen resultaat.
Behandel elk teken:
| Teken | Actie |
|---|---|
| Cijfer | num = num * 10 + digit |
| + of - | Tel sign * num op bij het resultaat, zet num terug op 0, stel het nieuwe teken in |
| ( | Push het resultaat en het teken, en reset beide |
| ) | Tel sign * num op bij het resultaat, vermenigvuldig dan met het opgeslagen teken en tel het opgeslagen resultaat erbij op |
| Spatie | Negeren |
Tel aan het einde de laatste sign * num erbij op.
def calculate(s):
result, sign, num = 0, 1, 0
stack = []
for ch in s:
if ch.isdigit():
num = num * 10 + int(ch)
elif ch in "+-":
result += sign * num
num = 0
sign = 1 if ch == "+" else -1
elif ch == "(":
stack.append(result)
stack.append(sign)
result, sign = 0, 1
elif ch == ")":
result += sign * num
num = 0
result *= stack.pop() # the sign before the parenthesis
result += stack.pop() # the result before the parenthesis
return result + sign * num
De pop-volgorde is belangrijk: het teken is als laatste gepusht, dus wordt als eerste gepopt.
Trace
Expressie: 1-(2+3).
| Teken | result | sign | num | stack |
|---|---|---|---|---|
| 1 | 0 | 1 | 1 | [] |
| - | 1 | -1 | 0 | [] |
| ( | 0 | 1 | 0 | [1, -1] |
| 2 | 0 | 1 | 2 | [1, -1] |
| + | 2 | 1 | 0 | [1, -1] |
| 3 | 2 | 1 | 3 | [1, -1] |
| ) | 5 dan 5 x (-1) = -5, dan -5 + 1 = -4 | 1 | 0 | [] |
| einde | -4 |
1 - (2 + 3) = -4, dat klopt.
Unaire min
Een minteken aan het begin werkt zonder speciale code. Aan het begin is num 0, dus de eerste - telt sign * 0 op bij het resultaat en zet dan het teken op -1. Hetzelfde geldt na een (: de opgeslagen toestand reset result naar 0 en sign naar +1, dus (-2) wordt op dezelfde manier behandeld.
Complexiteit
- Tijd: O(n), één pass over de string.
- Ruimte: O(n) in het slechtste geval bij diep geneste haakjes, omdat de stack twee waarden per open haakje bevat.
Ik heb deze functie getest op 4.000 willekeurige expressies met geneste haakjes en unaire mintekens, vergeleken met Python's eigen evaluatie, en alles kwam overeen.
Alternatief: recursie
Je kunt ook een recursieve functie schrijven die een expressie parseert en zichzelf aanroept wanneer die een ( tegenkomt. Het leest natuurlijk, maar het risico bestaat dat je de recursielimiet raakt bij diep geneste invoer, dus de stack-versie is veiliger in Python.
Uitbreidingen die interviewers vragen
| Variatie | Wat er verandert |
|---|---|
| Basic Calculator II (LeetCode 227) | Voegt * en / toe met prioriteit en zonder haakjes. Gebruik een stack van termen en pas * en / direct toe op de bovenste |
| Basic Calculator III (LeetCode 772) | Heeft alles: haakjes en * en /. Combineer beide ideeën, vaak met recursie |
| Variabelen of functies | Vereist een tokenizer en een parser |
| Grote getallen | Gebruik Python-integers, of handel overflow af in Java en C++ |
Randgevallen
| Invoer | Resultaat |
|---|---|
| "0" | 0 |
| " 7 " | 7 |
| "-1" | -1 |
| "(1)" | 1 |
| "2-(5-6)" | 3 |
| Veel geneste haakjes | Wordt afgehandeld door de stack |
| Getallen met meerdere cijfers zoals "123+4" | 127, omdat cijfers accumuleren |
Veelgemaakte fouten
- Elk cijfer als een apart getal behandelen.
- Vergeten de laatste sign * num aan het einde op te tellen.
- In de verkeerde volgorde poppen.
- num niet resetten na een operator.
- Een minteken aan het begin verkeerd behandelen.
Hoe je het uitlegt in een interview
- Verduidelijk de toegestane tekens, en of unaire min voorkomt.
- Zeg dat er geen prioriteitsprobleem is, dus haakjes zijn de enige uitdaging.
- Beschrijf de drie variabelen en wat een stack opslaat.
- Loop 1-(2+3) door op het whiteboard.
- Geef de complexiteit, en noem dan de Calculator II-uitbreiding.
Gerelateerde oefening
Zie onze Big O cheat sheet voor de complexiteitstermen, de AI LeetCode tutor guide, en de coding interview assistant guide. Valid Parentheses en Decode String gebruiken hetzelfde stack-idee.
Vertel je trace hardop terwijl je oefent. Een mock-interviewtranscript laat zien of je het doel van de stack hebt uitgelegd. Volg de regels van de werkgever over AI-tools bij elke live assessment.
Oefen coding-interviews met YesToTheOffer
Doe een mock coding-interview, vertel je trace hardop en bekijk achteraf je transcript. 30 gratis minuten, geen abonnement.



