문제 링크
https://www.acmicpc.net/problem/2493
풀이
첫 번째 시도 (메모리 초과)
- 우선 무난하게 브루트 포스로 접근했다. 하지만 낮은 정답 비율답게 오답 처리가 되었다. 예상했던 결과였으니 더 좋은 방법을 찾아봐야 했다.
소스 코드
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] tower = new int[n];
for (int i = 0; i < n; i++) {
tower[i] = sc.nextInt();
}
int[] result = new int[n];
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
if (tower[j] >= tower[i]) {
result[i] = j + 1;
break;
}
}
}
StringBuilder sb = new StringBuilder();
for (int r : result) {
sb.append(r + " ");
}
sb.setLength(sb.length() - 1);
System.out.println(sb.toString());
sc.close();
}
}
두 번째 시도 (시간 초과)
- 첫 번째 시도와는 다르게 스택을 사용하여 접근했다. 두 개의 스택을 사용하는데, 첫 번째 원소부터 스택에 넣고 현재 요소와 스택 안의 요소를 비교하면서 현재 탑이 더 놓으면 스택에 있는 탑을 두 번째 스택에 넣고 다음 요소와 비교하는 방식을 썼다. 그리고 현재 탑에 대해 비교가 끝나면 두 번째 스택의 모든 요소를 다시 첫 번째 스택으로 옮겨 담았다.
- 하지만 이번에는 시간 초과로 인해 오답 처리가 되었다.
Scanner
대신BufferedReader
를 사용했는 데도 틀렸다면 내 풀이가 잘못된 것이다.
소스 코드
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());
Stack<Integer> stack = new Stack<>();
Stack<Integer> temp = new Stack<>();
StringTokenizer st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= n; i++) {
int curr = Integer.parseInt(st.nextToken());
boolean isReceived = false;
while(!stack.isEmpty()) {
if (stack.peek() >= curr) {
// 이전 탑에서 수신했을 경우
isReceived = true;
break;
} else {
// 수신한 탑이 없을 경우
temp.push(stack.pop());
}
}
sb.append((isReceived ? stack.size() : 0) + " ");
while(!temp.isEmpty()) stack.push(temp.pop());
stack.push(curr);
}
sb.setLength(sb.length() - 1);
System.out.println(sb.toString());
br.close();
}
}
세 번째 시도
- 역시 내 풀이법이 잘못된 것이었다. 스택을 굳이 두 개 사용할 필요가 없었다.
- 탑을 역순으로 순회하면서 스택이 비었으면 삽입하고, 요소가 하나라도 있으면 맨 위 요소와 비교한다. 자신보다 더 높은 탑을 찾으면 결과 배열
result
에서 현재 인덱스curr
에 해당하는 값을 갱신하고 스택 연산을 계속 수행한다. 그리고 자신보다 높은 탑이 아니라면 현재 인덱스curr
를 스택에 삽입 후 루프를 계속 진행한다.- 여기서 스택에 삽입하는 요소는 탑의 높이가 아니라 인덱스이다.
소스 코드
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());
int[] tower = new int[n];
int[] result = new int[n];
Stack<Integer> stack = new Stack<>();
StringTokenizer st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) {
tower[i] = Integer.parseInt(st.nextToken());
}
for (int i = n - 1; i >= 0; i--) {
while(!stack.isEmpty()) {
int curr = stack.peek();
if (tower[i] < tower[curr]) break;
result[curr] = i + 1;
stack.pop();
}
stack.push(i);
}
for (int i = 0; i < n; i++) {
sb.append(result[i] + " ");
}
sb.setLength(sb.length() - 1);
System.out.println(sb.toString());
br.close();
}
}