백준
[백준 / JAVA] 2493. 탑
baefrica
2023. 6. 27. 03:49
반응형
https://www.acmicpc.net/problem/2493
2493번: 탑
첫째 줄에 탑의 수를 나타내는 정수 N이 주어진다. N은 1 이상 500,000 이하이다. 둘째 줄에는 N개의 탑들의 높이가 직선상에 놓인 순서대로 하나의 빈칸을 사이에 두고 주어진다. 탑들의 높이는 1
www.acmicpc.net
💻 풀이 결과
💯 최종 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
// 스택에 탑의 해당 위치와 높이를 쌍으로 저장해야한다.
class Tower {
int idx;
int height;
Tower(int idx, int height) {
this.idx = idx;
this.height = height;
}
}
public class Main {
public static void main(String[] args) throws IOException {
// 입력받는다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
// StringBuilder
StringBuilder sb = new StringBuilder();
// 스택 생성
Stack<Tower> stack = new Stack<>();
// 반복문 실행
for (int i = 0; i < N; i++) {
int curr = Integer.parseInt(st.nextToken()); // 현재 높이
// 앞에서부터 탐색한다...
// 처음에 스택이 비어있다면 -> 0 출력, 스택에 현재 값 push
if (stack.isEmpty()) {
sb.append(0).append(" ");
stack.push(new Tower(i + 1, curr));
}
// 스택이 비어있지 않다면
else {
while (true) {
// 예외 잘 체크하자!! : 하나씩 제거하다가 빈 스택이 될 경우...
if (stack.isEmpty()) {
// 나보다 높은 탑이 없으므로 0 출력 후 종료
sb.append(0).append(" ");
stack.push(new Tower(i + 1, curr));
break;
}
// 스택의 top 이 나보다 높다면 -> 바로 출력 후 현재 탑 push
if (stack.peek().height > curr) {
sb.append(stack.peek().idx).append(" ");
stack.push(new Tower(i + 1, curr));
break;
}
// 스택의 top 이 나보다 낮다면
else {
// top 은 어짜피 나보다 높이가 낮으니까 제거하면 된다.
stack.pop();
// 그리고 다음 꺼를 보러 간다.
continue;
}
}
}
}
// 출력
System.out.println(sb);
}
}
💢 틀린 이유
- 시간 초과가 발생을 했지만, 틀린 테스트 케이스도 발견을 할 수 있었기에 잘못된 로직인 것을 확인했다.
- 스택을 두 개 만들어서 왔다 갔다 하며 옮겨 담을 생각을 했다.
- 탑의 높이만을 스택에 저장하였고 인덱스는 그 값을 스택에 저장된 높이들과 비교해서 찾는 방식을 사용했는데, N의 크기가 큰 만큼 조회하는 시간이 오래 걸렸을 것 같다.
- 입력받은 탑의 높이들을 맨 뒤에서부터 비교하는 로직이었다.
틀린 풀이 과정
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
// 입력받는다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
// 현재 탑들의 높이가 담긴 스택 currStack 생성
Stack<Integer> currStack = new Stack<>();
for (int i = 0; i < N; i++) {
currStack.push(Integer.parseInt(st.nextToken()));
}
// 옴겨담을 스택 tmpStack 생성
Stack<Integer> tmpStack = new Stack<>();
// 결과 저장할 배열 생성
int[] answer = new int[N];
// 반복문 돌리기 전 초기 설정...
int tmp = currStack.peek(); // 맨 마지막 탑부터 시작
int currIdx = N - 1; // 현재 탑의 인덱스
while (true) {
// currStack 의 top 과 비교하기...
// 높이가 높으면 -> 수신 가능한 탑 찾았다!
if (currStack.peek() > tmp) {
// 정답 배열에 값 저장
answer[currIdx] = currStack.indexOf(currStack.peek()) + 1;
// 나머지는 원상복구시키고 tmp 는 삭제
while (tmpStack.size() > 1) {
currStack.push(tmpStack.pop());
}
tmpStack.pop();
// tmp 에 저장
tmp = currStack.peek();
// 현재 Idx 감소
currIdx--;
}
// 높이가 낮으면 -> 다음 탑의 높이 확인하러 가기
else {
tmpStack.push(currStack.pop());
}
// 탈출 조건...
// 현재 탑을 저장한 스택이 비었으면
if (currStack.isEmpty()) {
for (int i = currIdx; i >= 0; i--) {
answer[i] = 0;
}
break;
}
} // while문 끝
// 출력
StringBuilder sb = new StringBuilder();
for (int i : answer) {
sb.append(i).append(" ");
}
System.out.println(sb);
}
}
💬 풀이 과정
- 해당 탑의 위치와 높이를 쌍으로 저장할 Tower 클래스를 생성하였다.
- 생성한 스택에는 Tower 클래스 형태로 저장한다.
- 탑의 높이를 첫번째부터 왼쪽에서 읽어가며 비교한다.
- 처음 탑은 아무도 수신을 받지 못하기 때문에 0을 출력한다.
- 두 번째 탑부터는 차례대로 조건문을 보면서 스택의 top과 비교를 한다.
- 스택의 top 이 현재 탑보다 높이가 높다면 top 의 위치를 출력하고 현재 탑을 스택에 저장한다.
- 나보다 높이가 낮다면 스택의 top 을 삭제하고 다음 top과 비교를 하는 데, 이때 빈 스택이 된다면 0을 출력한다.
💡 깨달은 점
1. 클래스 생성
- 내가 쌍으로 저장하고 싶은 변수들을 담을 클래스를 생성해서 자료 구조의 형태로 이용한다.
2. 조건문 분기 처리를 잘하자!
- 예외 경우를 잘 생각하면서 조건문 분기 처리를 잘 구현해야 한다.
3. 스택 자료구조 활용하기
- 스택 자료구조에 대해 이해는 잘 하였으나, 좀 더 응용해서 활용하는 연습이 필요할 것 같다.
반응형