문제 풀이
오큰수를 다시 정리하면 다음과 같다.
나보다 크며, 오른쪽 중에서는 가장 작은 수여야 한다.
[3 5 2 7]에서 내가 5라고 가정하면, 오큰수는 7이다.
단순하게 완전 탐색으로 돌리게 되면 O(N^2)이 걸리게 된다.
N이 100만이기 때문에 시간 초과가 발생하므로 조금 더 빠르게 오큰수를 찾는 방법이 필요하다.
이런 문제는 스택 자료구조를 사용하면 O(N)으로 해결할 수 있게 된다.
스택은 아래와 같은 방법으로 동작한다.
1) 스택이 비어있으면 -1 (오큰수가 없으므로) 처리하고, 스택에 push 한다. 푸시하는 이유는 다음의 오큰수에 해당될 수 있으므로
2) 스택이 비어있지 않으면,
입력된 arr[i] < stack의 top이면? stack의 top이 해당 오큰수를 뜻하고,
>= 이면 <가 나올때까지 스택에서 계속해서 오큰수를 pop 하면서 찾는다.
만약에 찾게 된다면 해당 수가 오큰수이며, 입력된 arr[i]를 스택에 push 한다.
못 찾게 된다면 해당 수에 오큰수가 존재하지 않으므로 -1이다.
입력된 배열의 역순으로 하나씩 확인하면서 스택을 응용하면 된다.
문제에서 주어진 예시로 다시 확인해보자.
입력된 수 | 스택 자료구조 | 오큰수 배열 |
7 | empty | |
7 | [0, 0, 0, -1] | |
2 | 7 | |
7 2 | [0, 0, 7, -1] | |
5 | 7 2 | |
7 5 | [0, 7, 7, -1] | |
3 | 7 5 | |
7 5 3 | [5, 7, 7, -1] |
입력된 수 : 7
현재 스택이 비어있기 때문에 오큰수는 -1이며, 스택에 7을 삽입하면 된다.
입력된 수 : 2
현재 스택의 top(7)이 2보다 크므로 2의 오큰수는 7이며, 스택에 2를 삽입한다.
입력된 수 : 5
현재 스택의 top(2)보다 5가 더 크므로 스택에서 하나를 뺀다.
현재 스택의 top(7)이 5보다 크므로 5의 오큰수는 7이며, 스택에 5를 삽입한다.
입력된 수 : 3
현재 스택의 top(5)이 3보다 크므로 3의 오큰수는 5이며, 스택에 3을 삽입한다.
소스 코드
#include <iostream>
#include <stack>
using namespace std;
int N;
int arr[1000001];
int ans[1000001];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for(int i = 0; i < N; i++)
cin >> arr[i];
stack<int> st;
for(int i = N - 1; i >= 0; i--)
{
while(!st.empty() && st.top() <= arr[i])
st.pop();
if(!st.empty())
{
ans[i] = st.top();
}
else
ans[i] = -1;
st.push(arr[i]);
}
for(int i = 0; i < N; i++)
cout << ans[i] << ' ';
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준 2075] N번째 큰 수 (0) | 2021.10.13 |
---|---|
[백준 16926] 배열 돌리기1 (0) | 2021.10.12 |
[백준 14425] 문자열 집합 (0) | 2021.10.11 |
[백준 1753] 최단경로 (0) | 2021.10.11 |
[HackerRank] 2D Array - DS (0) | 2021.09.09 |