본문 바로가기
자바 알고리즘/백준

백준 17298 : 오큰수 (스택)

by hoshi03 2024. 6. 7.

문제

크기가 N인 수열 A = A1, A2, ..., AN이 있다. 수열의 각 원소 Ai에 대해서 오큰수 NGE(i)를 구하려고 한다. Ai의 오큰수는 오른쪽에 있으면서 Ai보다 큰 수 중에서 가장 왼쪽에 있는 수를 의미한다. 그러한 수가 없는 경우에 오큰수는 -1이다.

예를 들어, A = [3, 5, 2, 7]인 경우 NGE(1) = 5, NGE(2) = 7, NGE(3) = 7, NGE(4) = -1이다. A = [9, 5, 4, 8]인 경우에는 NGE(1) = -1, NGE(2) = 8, NGE(3) = 8, NGE(4) = -1이다.

입력

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

출력

총 N개의 수 NGE(1), NGE(2), ..., NGE(N)을 공백으로 구분해 출력한다.

예제 입력 1 복사

4
3 5 2 7

예제 출력 1 복사

5 7 7 -1

예제 입력 2 복사

4
9 5 4 8

예제 출력 2 복사

-1 8 8 -1


풀이

 

특정 원소 오른쪽에 있는 수 중에 특정 원소 보다 크면서 가장 가까운 수(가장 왼쪽에 있는 수)를 찾는 문제다

처음에는 스택을 어떻게 쓸지 감이 안왔는데
1. 배열 맨 뒤에서 시작해서 특정 원소보다 작으면 pop

2. 스택이 비었으면 자기보다 큰 수가 없으니 -1, 있음 peek를 가져오면 가장 최근에 넣은 자기보다 큰 수니 그 수가 오큰수

3. 특정 원소도 스택에 넣어서 비교가 가능하게 하기

과정을 알고 보면 굉장히 쉽게 풀리는데 뭔가 이런 씽크빅한 생각을 하는게 굉장히 힘들다..

 

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(br.readLine());
        int[] arr = Arrays.stream(br.readLine().split(" "))
                .mapToInt(Integer::parseInt)
                .toArray();

        int[] res = new int[n];

        Deque<Integer> stack = new ArrayDeque<>();
        // 맨 오른쪽에서 시작해서 왼쪽으로 진행하면서 오큰수를 찾는다
        for (int i = n - 1; i >= 0; i--) {
            // 스택의 맨 위 원소가 arr[i]보다 작으면 오큰수가 될수 없다
            while (!stack.isEmpty() && stack.peek() <= arr[i]) stack.pop();
            // 스택에 남아있는건 오른쪽부터 왼쪽 방향으로  차례대로 arr[i]보다 큰 원소니 
            // 가장 최근에 넣은 peek가 오른쪽에 있는 arr[i]보다 큰 수 중 가장 왼쪽에 있는 오큰수이다 
            res[i] = (stack.isEmpty() ? -1 : stack.peek());
            // 스택에 arr[i]를 넣고 반복문을 돌면서 arr[i-1]의 오큰수가 될수 있는지 판별한다
            stack.push(arr[i]);
        }

        StringBuilder sb = new StringBuilder();
        for (int x : res) bw.write(x + " ");
        bw.flush();
    }
}