
코딩테스트를 준비하다 보면 스택(Stack) 관련 문제를 정말 자주 마주치게 됩니다.
배열(int[])로도 구현할 수 있지만, 크기가 고정되어 있어 불편한 경우가 많죠.
이번 글에서는 ArrayList를 활용해서 스택처럼 사용하는 방법과 대표 예제들을 살펴볼게요.
스택은 LIFO(Last In, First Out) 구조입니다.
즉, 마지막에 넣은 데이터가 가장 먼저 나옵니다.
[Push] 1 → 2 → 3 (넣기)
[Pop] 3 → 2 → 1 (꺼내기)
현실 예시로는 접시 쌓기를 생각하면 됩니다.
마지막에 올린 접시를 제일 먼저 꺼내야 하죠.
| 비교 항목 | 배열 (int[]) | ArrayList |
|---|---|---|
| 크기 | 고정 (선언 시 결정) | 동적 (자동 확장) |
| 유연성 | 낮음 | 높음 |
| 코딩테스트 활용도 | 보통 | 높음 ✅ |
배열은 int[] stack = new int[100]; 처럼 크기를 미리 잡아야 해서
입력 크기가 유동적인 문제에서는 실수하기 쉽습니다.
ArrayList를 쓰면 이런 걱정이 사라집니다!
import java.util.ArrayList;
public class StackWithArrayList {
public static void main(String[] args) {
ArrayList<Integer> stack = new ArrayList<>();
// Push: 데이터 넣기
stack.add(1);
stack.add(2);
stack.add(3);
System.out.println("스택 상태: " + stack); // [1, 2, 3]
// Peek: 맨 위 데이터 확인 (꺼내지 않음)
int top = stack.get(stack.size() - 1);
System.out.println("Top: " + top); // 3
// Pop: 맨 위 데이터 꺼내기
int popped = stack.remove(stack.size() - 1);
System.out.println("Pop된 값: " + popped); // 3
System.out.println("스택 상태: " + stack); // [1, 2]
// isEmpty: 비어있는지 확인
System.out.println("비어있나요? " + stack.isEmpty()); // false
}
}
| 스택 연산 | ArrayList 코드 | 설명 |
|---|---|---|
| push | stack.add(value) | 맨 위에 추가 |
| pop | stack.remove(stack.size() - 1) | 맨 위 제거 후 반환 |
| peek | stack.get(stack.size() - 1) | 맨 위 확인 (제거 X) |
| isEmpty | stack.isEmpty() | 비어있는지 확인 |
| size | stack.size() | 현재 원소 개수 |
문제: 주어진 문자열에서 괄호가 올바르게 열리고 닫혔는지 확인하세요.
"(())" → true"(()(" → false")()" → falseimport java.util.ArrayList;
public class BracketCheck {
public static boolean isValid(String s) {
ArrayList<Character> stack = new ArrayList<>();
for (char c : s.toCharArray()) {
if (c == '(') {
// 여는 괄호면 push
stack.add(c);
} else { // c == ')'
// 닫는 괄호인데 스택이 비어있으면 false
if (stack.isEmpty()) return false;
// 맨 위의 여는 괄호를 pop
stack.remove(stack.size() - 1);
}
}
// 모두 처리 후 스택이 비어있어야 올바른 괄호
return stack.isEmpty();
}
public static void main(String[] args) {
System.out.println(isValid("(())")); // true
System.out.println(isValid("(()(")); // false
System.out.println(isValid(")(()")); // false
}
}
핵심 아이디어: 여는 괄호 (는 push, 닫는 괄호 )는 pop.
모든 처리 후 스택이 비어있으면 올바른 괄호입니다.
문제: 수열이 주어졌을 때, 각 원소의 오른쪽에서 처음으로 자신보다 큰 원소의 인덱스를 구하세요. 없으면 -1.
[2, 1, 4, 3][2, 2, -1, -1] (0-indexed)import java.util.ArrayList;
public class NextGreater {
public static int[] nextGreaterElement(int[] nums) {
int n = nums.length;
int[] result = new int[n];
// 스택에는 아직 정답을 못 찾은 인덱스를 저장
ArrayList<Integer> stack = new ArrayList<>();
for (int i = 0; i < n; i++) {
// 현재 값이 스택 top의 값보다 크면, top의 정답이 현재 인덱스
while (!stack.isEmpty() && nums[stack.get(stack.size() - 1)] < nums[i]) {
int idx = stack.remove(stack.size() - 1);
result[idx] = i;
}
stack.add(i);
}
// 스택에 남아있는 인덱스는 정답이 없음 → -1
while (!stack.isEmpty()) {
result[stack.remove(stack.size() - 1)] = -1;
}
return result;
}
public static void main(String[] args) {
int[] input = {2, 1, 4, 3};
int[] output = nextGreaterElement(input);
for (int v : output) System.out.print(v + " "); // 2 2 -1 -1
}
}
이 패턴은 단조 스택(Monotonic Stack) 이라 불리며, 히스토그램, 온도 문제 등에 자주 등장합니다.
문제: 후위 표기식 "3 4 + 2 *" 를 계산하세요. (결과: 14)
import java.util.ArrayList;
public class PostfixCalculator {
public static int calculate(String expression) {
ArrayList<Integer> stack = new ArrayList<>();
String[] tokens = expression.split(" ");
for (String token : tokens) {
if (token.equals("+") || token.equals("-")
|| token.equals("*") || token.equals("/")) {
// 피연산자 두 개 꺼내기
int b = stack.remove(stack.size() - 1);
int a = stack.remove(stack.size() - 1);
switch (token) {
case "+" -> stack.add(a + b);
case "-" -> stack.add(a - b);
case "*" -> stack.add(a * b);
case "/" -> stack.add(a / b);
}
} else {
// 숫자면 push
stack.add(Integer.parseInt(token));
}
}
return stack.get(0);
}
public static void main(String[] args) {
System.out.println(calculate("3 4 + 2 *")); // (3+4)*2 = 14
System.out.println(calculate("5 1 2 + 4 * + 3 -")); // 14
}
}
ArrayList를 스택으로 활용하면 크기 걱정 없이 유연하게 문제를 풀 수 있습니다.
코딩테스트에서 스택 문제를 만났을 때 아래 패턴만 기억하세요!
ArrayList<Integer> stack = new ArrayList<>();
stack.add(value); // push
stack.remove(stack.size() - 1); // pop
stack.get(stack.size() - 1); // peek
stack.isEmpty(); // 비어있는지 확인
스택이 자주 쓰이는 문제 유형:
Java에는
java.util.Stack클래스도 있지만, 공식 문서에서도Deque또는ArrayDeque사용을 권장합니다.
다만 코딩테스트에서 직관적인 구현을 원한다면ArrayList도 훌륭한 선택입니다! 🙂