문제
크기가 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();
}
}
'자바 알고리즘 > 백준' 카테고리의 다른 글
백준 18110 ( 구현, 정렬, 소수점 처리) (0) | 2024.11.18 |
---|---|
백준 15654 : n과 m (재귀) (0) | 2024.06.22 |
백준 2841 : 외계인의 기타 연주 (스택) (1) | 2024.06.07 |
백준 1874 : 스택 수열 (0) | 2024.06.06 |
백준 5397 : 키로거 (스택) (1) | 2024.06.06 |