
스택을 이렇게도 쓸 수 있구나 하고 깨달은 문제이다. 문제 자체는 간단해보이는데 시간제한내에 풀려면 스택을 꼭 써야한다. 그리고 출력시에도 주의가 필요하다.
풀기위해 필요한 필드는 입력받는 배열1, 결과값 저장하는 배열2, 빈 스택, 해서 총 3가지가 필요하다.
1. 배열1에 입력을 받는다.
2. 배열1의 마지막 값부터 스택값과 비교한다.
3-1. 스택이 비어있으면 -1을 배열2에 추가한다.
3-2. 스택 맨 위 값이 더 크면 오큰수이므로 peek()값을 배열2에 추가한다.
3-3. 스택 맨 위 값이 작거나 같으면, 스택 3-1, 3-2의 조건이 될때까지 pop()을 한다.
이렇게 설명하면 어려우니까 한 단계씩 풀어보자. 입력값 : 3 5 2 7 , 굵은 글씨가 스택이다.
- -> 7
7 -> 스택이 비어있음 -> -1, 스택에 7 추가
2
7 -> 7
2 -> 스택맨위값(7)보다 작음 -> 7, 스택에 2 추가
2 5
7 -> 7 -> 7
5 -> 스택맨위값(2)보다 큼 -> 2꺼내기(pop) -> 스택맨위값(7)보다 작음 -> 7, 스택에 5 추가
3
5 5
7 -> 7
3 -> 스택맨위값(5)보다 작음 -> 5, 스택에 3추가
<끝>
이렇게 푸는게 가능한 이유
- 오큰수는 N[i]와 N[i+1]를 비교한다. N[i]가 N[i+1]보다 작으면 답은 N[i+1]이고, N[i]가 N[i+1]보다 크면 N[i+1] 뒤의 값들을 보게된다.
- N[i+1] 뒤의 값들을 볼때, N[i+1]보다 작은 N[i+(2, 3...)]들은 볼 필요가 없다. 그래서 스택에서 지워지게된다. N[i+1]보다 큰 N[i+(2, 3...)]만 스택에 저장되고, N[i]와 비교하게 된다.
- X 5 2 1 7 을 예로 들면, X가 3일때 3 < 5(X < 5) 라서, 스택에 [5 2 1 7 이 있더라도 오큰수는 5가된다.
- X가 6일때 6 > 5(X > 5)라서, 5뒤의 숫자들을 보게된다. 그때 굳이 2, 1을 볼 필요가 없다. 2와 1은 5보다 작기 때문이다. 애초에 2와 1을 스택에 넣지 않아도 된다.
설명하는데도 꼬여서 이해가 잘 될지 모르겠다.. 스택으로 푸는건 알겠는데 왜 이렇게 풀 수 있는거야? 무슨 원리야?? 라는 질문이 스스로 들어서 연구(?)해봤다. 어렵다 어려워~
그리고 출력시에 그냥 ans배열을 하나씩 sout으로 출력했더니 시간초과가 났다..ㅎ BufferWriter를 쓰려다가 귀찮아서 sout썼는데... 이번에는 BufferWriter말고 얼마전에 쓴 StringBuilder를 활용해서 출력했고 시간초과가 나지 않았다~~
아래는 전체 코드이다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
public class BOJ17298 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Stack<Integer> stack = new Stack<>();
StringTokenizer st;
int N, i;
N = Integer.parseInt(br.readLine());
int[] NGE = new int[N];
int[] ans = new int[N];
// 입력값 배열에 저장
st = new StringTokenizer(br.readLine());
for(i=0;i<N;i++){
NGE[i] = Integer.parseInt(st.nextToken());
}
// 배열의 끝에서부터 오큰수 찾기
for(i=N-1;i>=0;i--){
while (!stack.isEmpty() && stack.peek() <= NGE[i]) // 현재 원소보다 크지않은 값 스택에서 제거
stack.pop();
if(stack.isEmpty()) // 스택이 비어있으면 오큰수는 -1
ans[i] = -1;
else if(stack.peek() > NGE[i]) // 스택값이 더 크면 오큰수
ans[i] = stack.peek();
stack.push(NGE[i]); // 한 턴이 끝났으니 값 추가
}
StringBuilder sb = new StringBuilder();
for (i = 0; i < N; i++)
sb.append(ans[i]).append(' ');
System.out.println(sb);
}
}
'코딩가딩가' 카테고리의 다른 글
| [JAVA]BOJ 15655, N과 M (6) (0) | 2024.09.06 |
|---|---|
| [JAVA]BOJ 15654, N과 M (5) (0) | 2024.09.06 |
| [JAVA]BOJ 1874, 스택 수열 (0) | 2024.08.31 |
| [JAVA]BOJ 16120, PPAP (0) | 2024.08.31 |
| [JAVA]BOJ 5397, 키로거 (0) | 2024.08.29 |