Implement k stacks in an array
                                        
                                                                                    
                                                
                                                    Last Updated : 
                                                    22 Sep, 2025
                                                
                                                 
                                                 
                                             
                                                                             
                                                             
                            
                            
                                                                                    
                
        
        Given two integers n and k. Implement k stacks using a single array of size n. Multiple stacks must share the same array space while supporting the following operations:
push(x, i): Push element x into the i-th stack.
pop(i): Pop the top element from the i-th stack and return it.
[Naive Approach] Dividing Array into k Segments
The idea is to divide the array into fixed parts, one for each stack. If the array size is n and there are k stacks, then each stack gets n/k slots.
We maintain another array top[] of size k, where top[i] stores the index of the top element of the i-th stack. Initially, all top[i] are set to the start of their respective segments minus one (indicating empty stacks).
Push is done by incrementing top[i] and inserting the element, while pop is done by returning the element at top[i] and then decrementing it.
 
 Limitation: This approach leads to inefficient space utilization, since one stack may become full even when other stacks still have free space available.
            C++
    #include <iostream>
#include <vector>
using namespace std;
class kStacks {
    
    // main array to store elements
    int *arr;    
    
    // stores top index for each stack
    int *top;    
    
    // size of each segment
    int segSize; 
public:
    kStacks(int n, int k) {
        segSize = n / k;
        arr = new int[n];
        top = new int[k];
        // initialize top pointers
        for (int i = 0; i < k; i++)
            top[i] = i * segSize - 1;
    }
    // push element x into stack i
    void push(int x, int i) {
        int end = (i + 1) * segSize - 1;
        if (top[i] == end) {
            cout << "Stack " << i << " overflow" << endl;
            return;
        }
        top[i]++;
        arr[top[i]] = x;
    }
    // pop element from stack i
    int pop(int i) {
        int start = i * segSize;
        if (top[i] < start) {
            cout << "Stack " << i << " underflow" << endl;
            return -1;
        }
        int val = arr[top[i]];
        top[i]--;
        return val;
    }
};
int main() {
    int n = 4, k = 2;
    kStacks st(n, k);
    // Each operations has the following format:
    // 1. Push operation → {1, value, stackNumber}
    // 2. Pop operation  → {2, stackNumber}
    vector<vector<int>> operations = {
        {1, 5, 0},  
        {1, 9, 0},
        {1, 10, 0}, 
        {1, 15, 1}, 
        {2, 0},
        {2, 1},
        {2, 1}
    };
    for (auto &op : operations) {
        
        if (op[0] == 1) { 
            int x = op[1], m = op[2];
            st.push(x, m);
        } else if (op[0] == 2) { 
            int m = op[1];
            int res = st.pop(m);
            if (res != -1)
                cout << "Popped Element: " << res << endl;
        }
    }
    return 0;
}
import java.util.Vector;
class kStacks {
    // main array to store elements
    private int[] arr;
    // stores top index for each stack
    private int[] top;
    // size of each segment
    private int segSize;
    public kStacks(int n, int k) {
        segSize = n / k;
        arr = new int[n];
        top = new int[k];
        // initialize top pointers
        for (int i = 0; i < k; i++)
            top[i] = i * segSize - 1;
    }
    // push element x into stack i
    public void push(int x, int i) {
        int end = (i + 1) * segSize - 1;
        if (top[i] == end) {
            System.out.println("Stack " + i + " overflow");
            return;
        }
        top[i]++;
        arr[top[i]] = x;
    }
    // pop element from stack i
    public int pop(int i) {
        int start = i * segSize;
        if (top[i] < start) {
            System.out.println("Stack " + i + " underflow");
            return -1;
        }
        int val = arr[top[i]];
        top[i]--;
        return val;
    }
}
public class GfG {
    public static void main(String[] args) {
        int n = 4, k = 2;
        kStacks st = new kStacks(n, k);
        // Each operations has the following format:
        // 1. Push operation → {1, value, stackNumber}
        // 2. Pop operation  → {2, stackNumber}
       int[][] operations = {
            {1, 5, 0},
            {1, 9, 0},
            {1, 10, 0},
            {1, 15, 1},
            {2, 0},
            {2, 1},
            {2, 1}
        };
        
        for (int[] op : operations) {
            if (op[0] == 1) {
                int x = op[1], m = op[2];
                st.push(x, m);
            } else if (op[0] == 2) {
                int m = op[1];
                int res = st.pop(m);
                if (res != -1)
                    System.out.println("Popped Element: " + res);
            }
        }
    }
}
class kStacks:
    # main array to store elements
    def __init__(self, n, k):
        self.segSize = n // k
        self.arr = [0] * n
        self.top = [i * self.segSize - 1 for i in range(k)]
    # push element x into stack i
    def push(self, x, i):
        end = (i + 1) * self.segSize - 1
        if self.top[i] == end:
            print(f'Stack {i} overflow')
            return
        self.top[i] += 1
        self.arr[self.top[i]] = x
    # pop element from stack i
    def pop(self, i):
        start = i * self.segSize
        if self.top[i] < start:
            print(f'Stack {i} underflow')
            return -1
        val = self.arr[self.top[i]]
        self.top[i] -= 1
        return val
if __name__ == '__main__':
    n = 4
    k = 2
    st = kStacks(n, k)
    # Each operation has the following format:
    # 1. Push operation → [1, value, stackNumber]
    # 2. Pop operation  → [2, stackNumber]
    operations = [
        [1, 5, 0],
        [1, 9, 0],
        [1, 10, 0],
        [1, 15, 1],
        [2, 0],
        [2, 1],
        [2, 1]
    ]
    
    for op in operations:
        if op[0] == 1:
            x = op[1]
            m = op[2]
            st.push(x, m)
        elif op[0] == 2:
            m = op[1]
            res = st.pop(m)
            if res != -1:
                print(f'Popped Element: {res}')
using System;
class kStacks {
    // main array to store elements
    private int[] arr;
    // stores top index for each stack
    private int[] top;
    // size of each segment
    private int segSize;
    public kStacks(int n, int k) {
        segSize = n / k;
        arr = new int[n];
        top = new int[k];
        // initialize top pointers
        for (int i = 0; i < k; i++)
            top[i] = i * segSize - 1;
    }
    // push element x into stack i
    public void push(int x, int i) {
        int end = (i + 1) * segSize - 1;
        if (top[i] == end) {
            Console.WriteLine("Stack " + i + " overflow");
            return;
        }
        top[i]++;
        arr[top[i]] = x;
    }
    // pop element from stack i
    public int pop(int i) {
        
        int start = i * segSize;
        if (top[i] < start) {
            Console.WriteLine("Stack " + i + " underflow");
            return -1;
        }
        int val = arr[top[i]];
        top[i]--;
        return val;
    }
}
class GfG {
    static void Main() {
        int n = 4, k = 2;
        kStacks st = new kStacks(n, k);
        // Each operation has the following format:
        // 1. Push operation → {1, value, stackNumber}
        // 2. Pop operation  → {2, stackNumber}
        int[][] operations = {
            new int[] {1, 5, 0},
            new int[] {1, 9, 0},
            new int[] {1, 10, 0},
            new int[] {1, 15, 1},
            new int[] {2, 0},
            new int[] {2, 1},
            new int[] {2, 1}
        };
        
        foreach (var op in operations) {
            if (op[0] == 1) {
                int x = op[1], m = op[2];
                st.push(x, m);
            } else if (op[0] == 2) {
                int m = op[1];
                int res = st.pop(m);
                if (res != -1)
                    Console.WriteLine("Popped Element: " + res);
            }
        }
    }
}
class kStacks {
    // main array to store elements
    arr;
    // stores top index for each stack
    top;
    // size of each segment
    segSize;
    constructor(n, k) {
        this.segSize = Math.floor(n / k);
        this.arr = new Array(n);
        this.top = new Array(k);
        // initialize top pointers
        for (let i = 0; i < k; i++)
            this.top[i] = i * this.segSize - 1;
    }
    // push element x into stack i
    push(x, i) {
        const end = (i + 1) * this.segSize - 1;
        if (this.top[i] === end) {
            console.log(`Stack ${i} overflow`);
            return;
        }
        this.top[i]++;
        this.arr[this.top[i]] = x;
    }
    // pop element from stack i
    pop(i) {
        const start = i * this.segSize;
        if (this.top[i] < start) {
            console.log(`Stack ${i} underflow`);
            return -1;
        }
        const val = this.arr[this.top[i]];
        this.top[i]--;
        return val;
    }
}
// Driver Code
const n = 4, k = 2;
const st = new kStacks(n, k);
// Each operation has the following format:
// 1. Push operation → [1, value, stackNumber]
// 2. Pop operation  → [2, stackNumber]
const operations = [
    [1, 5, 0],
    [1, 9, 0],
    [1, 10, 0],
    [1, 15, 1],
    [2, 0],
    [2, 1],
    [2, 1]
];
for (const op of operations) {
    if (op[0] === 1) {
        const x = op[1], m = op[2];
        st.push(x, m);
    } else if (op[0] === 2) {
        const m = op[1];
        const res = st.pop(m);
        if (res !== -1)
            console.log(`Popped Element: ${res}`);
    }
}
OutputStack 0 overflow
Poped Element: 9
Poped Element: 15
Stack 1 underflow
 Time Complexity: O(1) for push operation and pop operation
Auxiliary Space: O(n)
[Efficient Approach] Using Space Optimized Method
The idea is to allow all stacks to share the array dynamically instead of dividing it into fixed parts. For this, we use three additional structures:
- An array top[] of size k, where top[i] stores the index of the top element of the i-th stack.
- An array next[] of size n, which links free slots together and also helps connect elements within a stack.
- A variable freeTop that stores the index of the first free slot in the array.
Push Operation:
When we push an element into stack i, we pick the first free slot from freeTop. The element is placed at this index, and the next[] array is updated to link this slot with the previous top of stack i. Finally, top[i] is updated to this new index, and freeTop moves to the next available free slot.
Pop Operation:
When we pop from stack i, we look at the index stored in top[i]. The element at that index is removed, and top[i] is updated to the next link stored in next[]. The freed index is then added back to the free list by updating freeTop.
 Illustrations:
            C++
    #include <iostream>
using namespace std;
class kStacks {
    
    // main array to store elements
    int *arr;
    // array to store indexes of top elements of stacks
    int *top;
    // array to store next entry (for free list and stack links)
    int *next;
    // beginning index of free list
    int freeTop;
public:
    kStacks(int n, int k) {
        arr = new int[n];
        top = new int[k];
        next = new int[n];
        // initialize tops of all stacks as empty
        for (int i = 0; i < k; i++)
            top[i] = -1;
        // initialize free list
        freeTop = 0;
        for (int i = 0; i < n - 1; i++)
            next[i] = i + 1;
        next[n - 1] = -1;
    }
    // push element x into stack i
    void push(int x, int i) {
        if (freeTop == -1) {
            cout << "Stack Overflow\n";
            return;
        }
        // take index from free list
        int index = freeTop;     
        
        // update free list
        freeTop = next[index];
        
        // put element in array
        arr[index] = x;          
        
        // link new element to previous top
        next[index] = top[i];    
        
        // update top of stack
        top[i] = index;          
    }
    // pop element from stack i
    int pop(int i) {
        if (top[i] == -1) {
            cout << "Stack Underflow\n";
            return -1;
        }
        // get top index
        int index = top[i];      
        
        // update top to next element
        top[i] = next[index];    
        // add index back to free list
        next[index] = freeTop;   
        freeTop = index;
        // return popped element
        return arr[index];       
    }
};
int main() {
    int n = 9, k = 3;
    kStacks st(n, k);
    // Each query has the following format:
    // 1. Push operation → {1, value, stackNumber}
    // 2. Pop operation  → {2, stackNumber}
    int operations[][3] = {
        {1, 10, 1},
        {1, 20, 1},
        {1, 30, 1},
        {1, 100, 0},
        {1, 200, 0},
        {2, 1},
        {2, 1},
        {2, 0},
        {1, 2, 2}
    };
    
    int op = sizeof(operations) / sizeof(operations[0]);
    
    for (int i = 0; i < op; i++) {
        if (operations[i][0] == 1) {
            int x = operations[i][1], m = operations[i][2];
            st.push(x, m);
        } else if (operations[i][0] == 2) {
            int m = operations[i][1];
            int res = st.pop(m);
            if (res != -1)
                cout << "Popped Element: " << res << endl;
        }
    }
    return 0;
}
import java.util.Arrays;
class kStacks {
    // main array to store elements
    private int[] arr;
    // array to store indexes of top elements of stacks
    private int[] top;
    // array to store next entry (for free list and stack links)
    private int[] next;
    // beginning index of free list
    private int freeTop;
    public kStacks(int n, int k) {
        arr = new int[n];
        top = new int[k];
        next = new int[n];
        // initialize tops of all stacks as empty
        Arrays.fill(top, -1);
        // initialize free list
        freeTop = 0;
        for (int i = 0; i < n - 1; i++)
            next[i] = i + 1;
        next[n - 1] = -1;
    }
    // push element x into stack i
    public void push(int x, int i) {
        if (freeTop == -1) {
            System.out.println("Stack Overflow");
            return;
        }
        // take index from free list
        int index = freeTop;
        // update free list
        freeTop = next[index];
        // put element in array
        arr[index] = x;
        // link new element to previous top
        next[index] = top[i];
        // update top of stack
        top[i] = index;
    }
    // pop element from stack i
    public int pop(int i) {
        if (top[i] == -1) {
            System.out.println("Stack Underflow");
            return -1;
        }
        // get top index
        int index = top[i];
        // update top to next element
        top[i] = next[index];
        // add index back to free list
        next[index] = freeTop;
        freeTop = index;
        // return popped element
        return arr[index];
    }
}
public class Main {
    public static void main(String[] args) {
        int n = 9, k = 3;
        kStacks st = new kStacks(n, k);
        // Each operation has the following format:
        // 1. Push operation → {1, value, stackNumber}
        // 2. Pop operation  → {2, stackNumber}
        int[][] operations = {
            {1, 10, 1},
            {1, 20, 1},
            {1, 30, 1},
            {1, 100, 0},
            {1, 200, 0},
            {2, 1},
            {2, 1},
            {2, 0},
            {1, 2, 2}
        };
        
        int op = operations.length;
        
        for (int i = 0; i < op; i++) {
            if (operations[i][0] == 1) {
                int x = operations[i][1], m = operations[i][2];
                st.push(x, m);
            } else if (operations[i][0] == 2) {
                int m = operations[i][1];
                int res = st.pop(m);
                if (res != -1)
                    System.out.println("Popped Element: " + res);
            }
        }
    }
}
class kStacks:
    def __init__(self, n, k):
        self.arr = [0] * n
        self.top = [-1] * k
        self.next = [0] * n
        self.freeTop = 0
        for i in range(n - 1):
            self.next[i] = i + 1
        self.next[n - 1] = -1
    def push(self, x, i):
        if self.freeTop == -1:
            print("Stack Overflow")
            return
        index = self.freeTop
        self.freeTop = self.next[index]
        self.arr[index] = x
        self.next[index] = self.top[i]
        self.top[i] = index
    def pop(self, i):
        if self.top[i] == -1:
            print("Stack Underflow")
            return -1
        index = self.top[i]
        self.top[i] = self.next[index]
        self.next[index] = self.freeTop
        self.freeTop = index
        return self.arr[index]
if __name__ == '__main__':
    n = 9
    k = 3
    st = kStacks(n, k)
    # Each operation has the following format:
    # 1. Push operation → (1, value, stackNumber)
    # 2. Pop operation  → (2, stackNumber)
    operations = [
        (1, 10, 1),
        (1, 20, 1),
        (1, 30, 1),
        (1, 100, 0),
        (1, 200, 0),
        (2, 1),
        (2, 1),
        (2, 0),
        (1, 2, 2)
    ]
    
    for op in operations:
        if op[0] == 1:
            x, m = op[1], op[2]
            st.push(x, m)
        elif op[0] == 2:
            m = op[1]
            res = st.pop(m)
            if res != -1:
                print(f'Popped Element: {res}')
using System;
public class kStacks {
    
    // main array to store elements
    private int[] arr;
    // array to store indexes of top elements of stacks
    private int[] top;
    // array to store next entry (for free list and stack links)
    private int[] next;
    // beginning index of free list
    private int freeTop;
    public kStacks(int n, int k) {
        arr = new int[n];
        top = new int[k];
        next = new int[n];
        // initialize tops of all stacks as empty
        for (int i = 0; i < k; i++)
            top[i] = -1;
        // initialize free list
        freeTop = 0;
        for (int i = 0; i < n - 1; i++)
            next[i] = i + 1;
        next[n - 1] = -1;
    }
    // push element x into stack i
    public void push(int x, int i) {
        if (freeTop == -1) {
            Console.WriteLine("Stack Overflow");
            return;
        }
        // take index from free list
        int index = freeTop;
        // update free list
        freeTop = next[index];
        // put element in array
        arr[index] = x;
        // link new element to previous top
        next[index] = top[i];
        // update top of stack
        top[i] = index;
    }
    // pop element from stack i
    public int pop(int i) {
        if (top[i] == -1) {
            Console.WriteLine("Stack Underflow");
            return -1;
        }
        // get top index
        int index = top[i];
        // update top to next element
        top[i] = next[index];
        // add index back to free list
        next[index] = freeTop;
        freeTop = index;
        // return popped element
        return arr[index];
    }
}
public class GfG {
    public static void Main(string[] args) {
        int n = 9, k = 3;
        kStacks st = new kStacks(n, k);
        // Each operation has the following format:
        // 1. Push operation → {1, value, stackNumber}
        // 2. Pop operation  → {2, stackNumber}
        int[][] operations = {
            new int[] {1, 10, 1},
            new int[] {1, 20, 1},
            new int[] {1, 30, 1},
            new int[] {1, 100, 0},
            new int[] {1, 200, 0},
            new int[] {2, 1},
            new int[] {2, 1},
            new int[] {2, 0},
            new int[] {1, 2, 2}
        };
        
        int opCount = operations.Length;
        
        for (int i = 0; i < opCount; i++) {
            if (operations[i][0] == 1) {
                int x = operations[i][1], m = operations[i][2];
                st.push(x, m);
            }
            else if (operations[i][0] == 2) {
                int m = operations[i][1];
                int res = st.pop(m);
                if (res != -1)
                    Console.WriteLine("Popped Element: " + res);
            }
        }
    }
}
class kStacks {
    // main array to store elements
    arr;
    // array to store indexes of top elements of stacks
    top;
    // array to store next entry (for free list and stack links)
    next;
    // beginning index of free list
    freeTop;
    constructor(n, k) {
        this.arr = new Array(n);
        this.top = new Array(k);
        this.next = new Array(n);
        // initialize tops of all stacks as empty
        for (let i = 0; i < k; i++)
            this.top[i] = -1;
        // initialize free list
        this.freeTop = 0;
        for (let i = 0; i < n - 1; i++)
            this.next[i] = i + 1;
        this.next[n - 1] = -1;
    }
    // push element x into stack i
    push(x, i) {
        if (this.freeTop === -1) {
            console.log('Stack Overflow');
            return;
        }
        // take index from free list
        let index = this.freeTop;
        // update free list
        this.freeTop = this.next[index];
        // put element in array
        this.arr[index] = x;
        // link new element to previous top
        this.next[index] = this.top[i];
        // update top of stack
        this.top[i] = index;
    }
    // pop element from stack i
    pop(i) {
        if (this.top[i] === -1) {
            console.log('Stack Underflow');
            return -1;
        }
        // get top index
        let index = this.top[i];
        // update top to next element
        this.top[i] = this.next[index];
        // add index back to free list
        this.next[index] = this.freeTop;
        this.freeTop = index;
        // return popped element
        return this.arr[index];
    }
}
// Driver Code
let n = 9, k = 3;
let st = new kStacks(n, k);
// Each operation has the following format:
// 1. Push operation → [1, value, stackNumber]
// 2. Pop operation  → [2, stackNumber]
let operations = [
    [1, 10, 1],
    [1, 20, 1],
    [1, 30, 1],
    [1, 100, 0],
    [1, 200, 0],
    [2, 1],
    [2, 1],
    [2, 0],
    [1, 2, 2]
];
let opCount = operations.length;
for (let i = 0; i < opCount; i++) {
    if (operations[i][0] === 1) {
        let x = operations[i][1], m = operations[i][2];
        st.push(x, m);
    } else if (operations[i][0] === 2) {
        let m = operations[i][1];
        let res = st.pop(m);
        if (res !== -1)
            console.log('Popped Element: ' + res);
    }
}
OutputPopped Element: 30
Popped Element: 20
Popped Element: 200
 Time Complexity: O(1) for push operation and pop operation
Auxiliary Space: O(n)
Related Article: 
                                
                                
                            
                                                                                
                                                            
                                                    
                                                
                                                        
                            
                        
                                                
                        
                                                                                    
                                                                Explore
                                    
                                        DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem