๐ฅ Stack Computation: The Magic Pancake Counter
Ever wonder how calculators solve complex math? Or how computers decode secret messages? Letโs discover the magic of Stack Computation!
๐ฏ What Youโll Master
Imagine you have a stack of pancakes. You can only add or remove pancakes from the TOP. This simple rule makes stacks incredibly powerful for solving tricky problems!
graph TD A["๐ฅ Pancake Stack"] --> B["Add to TOP only"] A --> C["Remove from TOP only"] B --> D["Last In, First Out"] C --> D
1๏ธโฃ Min Stack: The Smart Pancake Counter
๐ค The Problem
Youโre stacking pancakes and your friend keeps asking: โWhatโs the smallest pancake in the stack RIGHT NOW?โ
Checking every pancake each time would be slow! Can we answer instantly?
๐ก The Trick: Two Stacks!
Keep a helper stack that always tracks the smallest value seen so far.
class MinStack {
constructor() {
this.stack = [];
this.minStack = []; // Helper!
}
push(val) {
this.stack.push(val);
// Track minimum at this point
const currentMin =
this.minStack.length === 0
? val
: Math.min(val, this.minStack.at(-1));
this.minStack.push(currentMin);
}
pop() {
this.stack.pop();
this.minStack.pop();
}
getMin() {
return this.minStack.at(-1); // Instant!
}
}
๐ฎ Example Walkthrough
| Action | Stack | Min Stack | getMin() |
|---|---|---|---|
| push(5) | [5] | [5] | 5 |
| push(2) | [5,2] | [5,2] | 2 |
| push(7) | [5,2,7] | [5,2,2] | 2 |
| pop() | [5,2] | [5,2] | 2 |
Magic: We always know the minimum without searching! ๐ฉ
2๏ธโฃ Expression Parsing: Reading Math Like a Story
๐ค The Challenge
How does a computer understand 3 + 4 * 2? It doesnโt just read left-to-right like us!
๐ก The Secret: Operator Priority
Think of it like a VIP line:
- ร and รท are VIPs (go first)
- + and โ wait their turn
graph TD A["3 + 4 * 2"] --> B["See: 3"] B --> C["See: +"] C --> D["See: 4"] D --> E["See: *"] E --> F["* is VIP! Calculate 4*2 first"] F --> G["Result: 3 + 8 = 11"]
๐ฏ Two Stacks Save the Day
function evaluate(expression) {
const nums = [];
const ops = [];
const priority = {'+':1, '-':1, '*':2, '/':2};
function applyOp() {
const b = nums.pop();
const a = nums.pop();
const op = ops.pop();
if (op === '+') nums.push(a + b);
if (op === '-') nums.push(a - b);
if (op === '*') nums.push(a * b);
if (op === '/') nums.push(Math.trunc(a / b));
}
// Parse character by character...
// Push numbers to nums stack
// Handle operators based on priority
return nums[0];
}
Key Insight: Before adding a new operator, compute any waiting VIPs first!
3๏ธโฃ Basic Calculator: The Bracket Master
๐ค The Puzzle
2 * (3 + 4) โ How do we handle brackets?
๐ก Brackets Are Like Pause Buttons!
When you see (:
- Save your current work
- Start fresh inside brackets
When you see ):
- Finish bracket calculation
- Resume saved work
function calculate(s) {
const stack = [];
let num = 0;
let result = 0;
let sign = 1;
for (const char of s) {
if (char >= '0' && char <= '9') {
num = num * 10 + Number(char);
} else if (char === '+') {
result += sign * num;
num = 0;
sign = 1;
} else if (char === '-') {
result += sign * num;
num = 0;
sign = -1;
} else if (char === '(') {
// SAVE current state
stack.push(result);
stack.push(sign);
result = 0;
sign = 1;
} else if (char === ')') {
result += sign * num;
num = 0;
// RESTORE saved state
result *= stack.pop(); // sign
result += stack.pop(); // previous result
}
}
return result + sign * num;
}
๐ฎ Example: 1 + (2 - 3)
| Step | Action | Stack | Result |
|---|---|---|---|
1 |
num = 1 | [] | 0 |
+ |
result = 1 | [] | 1 |
( |
save state | [1, 1] | 0 |
2 |
num = 2 | [1, 1] | 0 |
- |
result = 2 | [1, 1] | 2 |
3 |
num = 3 | [1, 1] | 2 |
) |
finish & restore | [] | 0 |
4๏ธโฃ Decode String: The Secret Message Unlocker
๐ค The Mystery
3[ab2[c]] means โrepeat ab2[c] three timesโโฆ but whatโs inside?
๐ก Work from Inside Out!
Like Russian nesting dolls ๐ช โ open the innermost first!
graph TD A["3[ab2[c]]"] --> B["Find innermost: 2[c]"] B --> C["Decode: cc"] C --> D["Now have: 3[abcc]"] D --> E["Decode: abccabccabcc"]
๐ฏ The Stack Solution
function decodeString(s) {
const countStack = [];
const stringStack = [];
let currentStr = '';
let k = 0;
for (const char of s) {
if (char >= '0' && char <= '9') {
k = k * 10 + Number(char);
} else if (char === '[') {
// SAVE current progress
countStack.push(k);
stringStack.push(currentStr);
currentStr = '';
k = 0;
} else if (char === ']') {
// DECODE and combine
const count = countStack.pop();
const prevStr = stringStack.pop();
currentStr = prevStr +
currentStr.repeat(count);
} else {
currentStr += char;
}
}
return currentStr;
}
๐ฎ Walkthrough: 2[a3[b]]
| Char | Action | String Stack | Count Stack | Current |
|---|---|---|---|---|
2 |
k=2 | [] | [] | โโ |
[ |
save | [โโ] | [2] | โโ |
a |
add | [โโ] | [2] | โaโ |
3 |
k=3 | [โโ] | [2] | โaโ |
[ |
save | [โโ,โaโ] | [2,3] | โโ |
b |
add | [โโ,โaโ] | [2,3] | โbโ |
] |
decode | [โโ] | [2] | โabbbโ |
] |
decode | [] | [] | โabbbabbbโ |
5๏ธโฃ Asteroid Collision: The Space Battle
๐ค The Scenario
Asteroids fly in a line. Positive = right โ, Negative = left โ
When they collide:
- Bigger one survives
- Same size? Both explode! ๐ฅ
๐ก Think Like a Space Traffic Controller
Process asteroids left to right. Use a stack to track survivors!
function asteroidCollision(asteroids) {
const stack = [];
for (const ast of asteroids) {
let destroyed = false;
// Collision: top going right, current going left
while (
stack.length > 0 &&
stack.at(-1) > 0 &&
ast < 0
) {
const top = stack.at(-1);
if (top < Math.abs(ast)) {
stack.pop(); // Top destroyed
} else if (top === Math.abs(ast)) {
stack.pop(); // Both destroyed
destroyed = true;
break;
} else {
destroyed = true; // Current destroyed
break;
}
}
if (!destroyed) {
stack.push(ast);
}
}
return stack;
}
๐ฎ Battle Simulation: [5, 10, -5]
| Asteroid | Stack Before | Action | Stack After |
|---|---|---|---|
| 5โ | [] | Add | [5] |
| 10โ | [5] | Add | [5, 10] |
| โ5 | [5, 10] | 10 vs 5: 10 wins | [5, 10] |
Result: [5, 10] โ The small asteroid was destroyed!
6๏ธโฃ Remove K Digits: Make the Smallest Number
๐ค The Challenge
Given "1432219" and k=3, remove 3 digits to make the smallest number.
๐ก The Greedy Stack Strategy
Scan left to right. If a digit is bigger than the next one, itโs a good candidate to remove!
graph TD A["1432219, remove 3"] --> B["1 < 4: keep 1"] B --> C["4 > 3: remove 4"] C --> D["3 > 2: remove 3"] D --> E["2 > 1: remove 2"] E --> F["Result: 1219"]
๐ฏ The Stack Solution
function removeKdigits(num, k) {
const stack = [];
for (const digit of num) {
// Remove larger digits from stack
while (
k > 0 &&
stack.length > 0 &&
stack.at(-1) > digit
) {
stack.pop();
k--;
}
stack.push(digit);
}
// Remove remaining from end
while (k > 0) {
stack.pop();
k--;
}
// Remove leading zeros
const result = stack.join('')
.replace(/^0+/, '');
return result || '0';
}
๐ฎ Example: "1432219", k=3
| Digit | Stack | k | Action |
|---|---|---|---|
| 1 | [1] | 3 | push |
| 4 | [1,4] | 3 | push |
| 3 | [1,3] | 2 | pop 4, push 3 |
| 2 | [1,2] | 1 | pop 3, push 2 |
| 2 | [1,2,2] | 1 | push |
| 1 | [1,2,1] | 0 | pop 2, push 1 |
| 9 | [1,2,1,9] | 0 | push |
Result: "1219" โจ
๐ You Did It!
Youโve mastered the six superpowers of Stack Computation:
| Problem | Key Insight |
|---|---|
| Min Stack | Two stacks track everything |
| Expression Parsing | Operators have VIP levels |
| Basic Calculator | Brackets = Save & Resume |
| Decode String | Innermost first, like nesting dolls |
| Asteroid Collision | Process & battle survivors |
| Remove K Digits | Greedily remove larger digits |
graph LR A["๐ฅ Stack"] --> B["Min Stack"] A --> C["Calculators"] A --> D["String Decoding"] A --> E["Simulations"] A --> F["Optimization"] B --> G["โจ O#40;1#41; minimum"] C --> H["โจ Handle any expression"] D --> I["โจ Nested patterns"] E --> J["โจ Collision detection"] F --> K["โจ Greedy removal"]
Remember: Stacks are simple (Last In, First Out), but combined with clever thinking, they solve incredibly complex problems!
๐ Now go stack up your skills!
