Stack Implementation Using Array in DSA Go - Time & Space Complexity
We want to understand how fast stack operations run when using an array.
How does the time to push or pop items change as the stack grows?
Analyze the time complexity of the following code snippet.
package main
import "fmt"
type Stack struct {
items []int
}
func (s *Stack) Push(val int) {
s.items = append(s.items, val)
}
func (s *Stack) Pop() int {
if len(s.items) == 0 {
return -1
}
val := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return val
}
func main() {
s := Stack{}
s.Push(10)
s.Push(20)
fmt.Println(s.Pop())
}
This code shows a stack using an array where we add (push) and remove (pop) items at the end.
Look at the main repeated actions:
- Primary operation: Adding or removing an item at the end of the array.
- How many times: Each push or pop happens once per call, no loops inside.
Each push or pop takes about the same time no matter how many items are in the stack.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 pushes = 10 operations |
| 100 | 100 pushes = 100 operations |
| 1000 | 1000 pushes = 1000 operations |
Pattern observation: Time grows linearly with number of operations, but each operation is constant time.
Time Complexity: O(1)
This means each push or pop runs in constant time, no matter how big the stack is.
[X] Wrong: "Push or pop takes longer as the stack grows because the array is bigger."
[OK] Correct: We only add or remove at the end, so no need to move other items. The operation stays quick.
Knowing that stack operations are constant time helps you explain why stacks are efficient for many tasks like undo or expression evaluation.
"What if we changed the stack to add or remove items at the start of the array? How would the time complexity change?"
Practice
Solution
Step 1: Understand stack behavior
A stack stores elements so the last added is the first removed, called LIFO.Step 2: Role of array in stack
An array holds elements in order, supporting push/pop at one end to maintain LIFO.Final Answer:
To store elements in a last-in, first-out (LIFO) order -> Option CQuick Check:
Stack = LIFO [OK]
- Confusing stack with queue (FIFO)
- Thinking array sorts elements automatically
- Assuming random access is main stack feature
Solution
Step 1: Understand Go slice declaration
In Go, slices are dynamic arrays declared as []type{}, e.g., []int{}.Step 2: Check options for correct syntax
stack := []int{} uses correct slice literal syntax to create an empty int slice.Final Answer:
stack := []int{} -> Option AQuick Check:
Go slice syntax = []type{} [OK]
- Using array keyword incorrectly
- Wrong order of type and brackets
- Declaring fixed size array instead of slice
package main
import "fmt"
func main() {
stack := []int{}
stack = append(stack, 10)
stack = append(stack, 20)
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println(top)
fmt.Println(stack)
}Solution
Step 1: Trace push operations
stack starts empty, append 10 -> [10], append 20 -> [10, 20]Step 2: Trace pop operation
top = last element = 20, then remove last element -> stack becomes [10]Final Answer:
20 [10] -> Option BQuick Check:
Pop returns 20, stack left with 10 [OK]
- Printing stack before pop
- Confusing first element with last
- Not slicing stack correctly after pop
package main
func main() {
var stack []int
stack[len(stack)] = 5
}Solution
Step 1: Understand slice indexing
Accessing stack[len(stack)] tries to assign beyond current slice length, causing error.Step 2: Correct push uses append
To add element, use append(stack, 5) instead of direct index assignment.Final Answer:
Index out of range error -> Option AQuick Check:
Assigning at len(slice) causes index error [OK]
- Trying to assign at slice length index
- Forgetting to import fmt (not needed here)
- Assuming slice auto-expands on index assignment
Solution
Step 1: Understand pop risk on empty stack
Popping from empty slice causes index out of range runtime error.Step 2: Add length check before pop
Check if len(stack) == 0; if yes, return error or zero value to avoid crash.Final Answer:
Check if stack length is zero before popping and return an error or zero value -> Option DQuick Check:
Empty stack pop needs length check [OK]
- Ignoring empty stack check causing runtime panic
- Using map instead of array unnecessarily
- Trying to pop all elements in a loop without condition
Ready to prove it?
Pass the test and this pattern moves unknown
