π Stack in JavaScript β Complete Guide with Array & Linked List Implementation
Stack in JavaScript

A Stack is one of the most fundamental data structures in computer science. It follows the LIFO (Last In, First Out) principle β the last element inserted is the first one to be removed.
Think of a stack of plates:
You place plates on top, and remove from the top.
π§ What is a Stack?
A stack supports mainly four operations:
| Operation | Description |
push() | Add an element to the top |
pop() | Remove the top element |
peek() | View top element without removing |
isEmpty() | Check if stack is empty |
Simple and powerful β perfect for problems like
β undo-redo
β backtracking
β browser history
β valid parentheses
β next greater element
π Stack Implementation Using Array
This is the simplest and most commonly used approach in JavaScript.
class Stack {
constructor() {
this.stack = [];
}
push(item) {
this.stack.push(item);
}
pop() {
if (this.isEmpty()) {
return null;
}
return this.stack.pop();
}
peek() {
if (this.isEmpty()) {
return null;
}
return this.stack[this.stack.length - 1];
}
isEmpty() {
return this.stack.length === 0;
}
size() {
return this.stack.length;
}
}
const stack = new Stack();
stack.push(10);
stack.push(12);
stack.push(13);
stack.push(15);
stack.push(17);
stack.pop();
console.log(stack.peek());
console.log(stack);
β Output
15
Stack { stack: [ 10, 12, 13, 15 ] }
π Stack Implementation Using Linked List
A Linked Listβbased stack allows faster memory allocation and avoids array resizing.
Visualizing the Stack (Linked List)
(top)
β
[14] β [12] β [10] β null
Implementation
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class StackLinkedList {
constructor() {
this.top = null;
this.size = 0;
}
push(data) {
const newNode = new Node(data);
newNode.next = this.top;
this.top = newNode;
this.size++;
}
pop() {
if (this.isEmpty()) {
return "List is already empty";
}
const item = this.top.data;
this.top = this.top.next;
this.size--;
return item;
}
peek() {
return this.top?.data || null;
}
isEmpty() {
return this.size === 0;
}
}
const stack1 = new StackLinkedList();
stack1.push(10);
stack1.push(12);
stack1.push(14);
console.log(stack1.pop());
console.log(stack1.peek());
console.log(stack1);
β Output
14
12
StackLinkedList { top: Node { data: 12, next: Node { data: 10, next: null } }, size: 2 }
π Array vs Linked List Stack
| Feature | Array Stack | Linked List Stack |
| Speed | Fast (O(1)) | Fast (O(1)) |
| Memory | Contiguous | Dynamic |
| Overflow | Possible | No |
| Implementation | Simpler | Slightly harder |
Both are goodβuse Array for simplicity and Linked List for flexibility.
π§© Practice Stack Problems
Here are must-solve interview questions based on stacks:
Remove All Adjacent Duplicates in a String
Valid Parentheses
Backspace String Compare
Next Greater Element I
Online Stock Span
Next Greater Element II
Remove K Digits
Sum of Subarray Minimums
β 1. Remove All Adjacent Duplicates in String
Problem
Remove pairs of adjacent duplicate characters until no duplicates remain.
Stack Solution
var removeDuplicates = function(s) {
const stack = [];
for (let ch of s) {
if (stack.length && stack[stack.length - 1] === ch) {
stack.pop(); // remove duplicate
} else {
stack.push(ch);
}
}
return stack.join('');
};
console.log(removeDuplicates("abbaca")); // "ca"
β 2. Valid Parentheses
Problem
Check if parentheses are correctly balanced.
Stack Solution
var isValid = function(s) {
const stack = [];
const map = {
')': '(',
']': '[',
'}': '{'
};
for (let ch of s) {
if (ch in map) {
if (stack.pop() !== map[ch]) return false;
} else {
stack.push(ch);
}
}
return stack.length === 0;
};
console.log(isValid("()[]{}")); // true
console.log(isValid("(]")); // false
β 3. Backspace String Compare
Problem
# means backspace. Compare final strings.
Stack Solution
var build = function(s) {
const stack = [];
for (let ch of s) {
if (ch === '#') stack.pop();
else stack.push(ch);
}
return stack.join('');
};
var backspaceCompare = function(s, t) {
return build(s) === build(t);
};
console.log(backspaceCompare("ab#c", "ad#c")); // true
β 4. Next Greater Element I
Problem
For each element in nums1, find next greater in nums2.
Stack + Map Solution
var nextGreaterElement = function(nums1, nums2) {
const stack = [];
const map = new Map();
for (let num of nums2) {
while (stack.length && num > stack[stack.length - 1]) {
map.set(stack.pop(), num);
}
stack.push(num);
}
return nums1.map(n => map.get(n) || -1);
};
console.log(nextGreaterElement([4,1,2], [1,3,4,2])); // [-1,3,-1]
β 5. Online Stock Span
Problem
For each day's price, find how many consecutive previous days have price β€ current.
Monotonic Stack Solution
var StockSpanner = function() {
this.stack = []; // [price, span]
};
StockSpanner.prototype.next = function(price) {
let span = 1;
while (this.stack.length && this.stack[this.stack.length - 1][0] <= price) {
span += this.stack.pop()[1];
}
this.stack.push([price, span]);
return span;
};
// Example
const ss = new StockSpanner();
console.log(ss.next(100));
console.log(ss.next(80));
console.log(ss.next(60));
console.log(ss.next(70));
console.log(ss.next(60));
console.log(ss.next(75));
console.log(ss.next(85));
β 6. Next Greater Element II (Circular Array)
Problem
Return next greater element in circular array.
Stack + Mod Index Solution
var nextGreaterElements = function(nums) {
const n = nums.length;
const res = new Array(n).fill(-1);
const stack = [];
for (let i = 0; i < 2 * n; i++) {
let num = nums[i % n];
while (stack.length && num > nums[stack[stack.length - 1]]) {
res[stack.pop()] = num;
}
if (i < n) stack.push(i);
}
return res;
};
console.log(nextGreaterElements([1,2,1])); // [2, -1, 2]
β 7. Remove K Digits
Problem
Remove k digits to make smallest number.
Monotonic Stack Solution
var removeKdigits = function(num, k) {
const stack = [];
for (let digit of num) {
while (k > 0 && stack.length && stack[stack.length - 1] > digit) {
stack.pop();
k--;
}
stack.push(digit);
}
while (k > 0) {
stack.pop();
k--;
}
let result = stack.join('').replace(/^0+/, '');
return result === '' ? '0' : result;
};
console.log(removeKdigits("1432219", 3)); // "1219"
β 8. Sum of Subarray Minimums
Problem
Sum of minimum element of every subarray.
Hard β uses Monotonic Stack for previous less + next less.
var sumSubarrayMins = function(arr) {
const n = arr.length;
const mod = 1e9 + 7;
const prev = new Array(n).fill(-1);
const next = new Array(n).fill(n);
let stack = [];
// previous less element
for (let i = 0; i < n; i++) {
while (stack.length && arr[stack[stack.length - 1]] > arr[i]) {
stack.pop();
}
prev[i] = stack.length ? stack[stack.length - 1] : -1;
stack.push(i);
}
stack = [];
// next less or equal element
for (let i = 0; i < n; i++) {
while (stack.length && arr[stack[stack.length - 1]] >= arr[i]) {
next[stack.pop()] = i;
}
stack.push(i);
}
let result = 0;
for (let i = 0; i < n; i++) {
const left = i - prev[i];
const right = next[i] - i;
result = (result + arr[i] * left * right) % mod;
}
return result;
};
console.log(sumSubarrayMins([3,1,2,4])); // 17
π― Final Thoughts
Stacks are incredibly powerful. Once you understand push/pop/peek and the LIFO principle, solving many coding problems becomes easier.



