ALGORITHM/BOJ

[백준] 17298 오큰수

0298 2022. 7. 25. 20:14

https://www.acmicpc.net/problem/17298

 

17298번: 오큰수

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에 수열 A의 원소 A1, A2, ..., AN (1 ≤ Ai ≤ 1,000,000)이 주어진다.

www.acmicpc.net

2022-07-25


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.StringTokenizer;
 
public class Main17298 {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(bf.readLine().trim());
        int N = Integer.parseInt(st.nextToken());
 
        st = new StringTokenizer(bf.readLine());
 
        int[] arr = new int[N];
        // 1) 수열 입력 받기
        for(int i = 0; i < N; i++) arr[i] = Integer.parseInt(st.nextToken());
 
        Stack<Integer> s = new Stack<>();
        // 2) stack, 0번째 index push;
        s.push(0);
        int[] answer = new int[N];
 
        for(int i = 1; i < N; i++) {
            if(s.isEmpty()) s.push(i);
 
            // 3) stack이 비어있지 않고, 현재 stack의 top에 있는 index의 값과 현재 index와 비교
            while(!s.isEmpty() && arr[s.peek()] < arr[i]) {
                answer[s.pop()] = arr[i];
            }
            s.push(i);
        }
 
        // 4) 끝까지 다 체크 했는데 아직 stack에 index가 남아있는 경우
        while(!s.isEmpty()) {
            answer[s.pop()] = -1;
        }
 
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < answer.length; i++) sb.append(answer[i]).append(" ");
 
        System.out.println(sb.toString());
    }
}
cs

#문제풀이

 

시간초과와 틀렸습니다를 반복하고 결국 블로그를 찾아봤다. 알고 나니 왜 value가 아닌 index를 사용할 생각을 못했지라는 생각이 들었다. 

 

이 문제는 stack에 index값을 넣어서 풀 수 있는 문제이다. 

처음 입력 받은 arr와 index 값을 넣을 stack, 그리고 answer 3개를 세트로 생각하고 푼다.

 

1) 수열 입력 받기

2) stack에 0번째 index push 하기 

 

 

 

3) for문을 1부터 n-1까지 돌면서 오큰수를 찾는다.

 while(!s.isEmpty() && arr[s.peek()] < arr[i]) {
       answer[s.pop()] = arr[i];
}
 s.push(i);

 

 

 

3-1) 위 초기 세팅 기준으로 현재 stack.peek은 index 0이고, for문의 Index값은 1이다.

 

그러면 arr[0] 즉, 3과 arr[1] 즉 5 를 비교할 수 있다. arr[s.peek()] < arr[i] 이므로, arr[0]의 오큰수는 arr[1]이 맞다.

오큰수를 찾았기 때문에 stack에서 pop을 하고, 해당 index값에 오큰수를 부여할 수 있다. 그리고 stack에 남아있는 값이 없어서 while문을 빠져나가게 된다.

 

그리고 다음 index값을 stack에 넣어주었다.

 

 

 

 

 

3-2) 현재 기준으로 stack.peek()은 index 1이고, for문의 index 값은 2 이다.

arr[1]과 arr[2]를 비교하게 되는데 arr[1]은 5이고, arr[2]는 2로 arr[1]이 더 크기 때문에 arr[2]는 arr[1]의 오큰수가 아니다. 

 

 

 

 

 

 

3-3) 현재 기준으로 stack.peek()은 index 2이고, for문의 기준 index값은 3이다. 

arr[2]와 arr[3]을 비교하게 되는데 arr[2]는 2이고 arr[3]은 7이므로 arr[2]의 오큰수는 7이 되고 2는 stack에서 pop된다.

아까 코드를 다시 보면 while문 이므로, 그 다음에 있던 index값 1을 찾을 수 있다. 따라서 arr[1]은 5이고 arr[3]은 7이므로 arr[1]의 오큰수는 7이 되고 stack에서 pop된다.

 while(!s.isEmpty() && arr[s.peek()] < arr[i]) {
       answer[s.pop()] = arr[i];
}

 

 

 

 

3-4) stack에 마지막 index 3이 push가 되었지만, 마지막 index값이라 for문에서 빠져나오게 된다.

 

 

4) for문을 빠져나왔지만 아직 stack에 값이 있으므로, 해당 stack에 있는 모든 값들을 오큰수가 없다고 판단하여 해당 index에 -1로 처리를 해주어야 한다.

while(!s.isEmpty()) {
      answer[s.pop()] = -1;
}