알고리즘 풀이/백준

[백준 17298] 오큰수

iwannawebfullstack 2021. 6. 13. 22:01

문제

크기가 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)을 공백으로 구분해 출력한다.


접근

처음에 왼쪽부터 순차적으로 탐색하여 설계를 하였을 때 오큰수를 찾을 수 없었다. 이전의 기록들을 살펴보면서 해를 구해야하는데 왼쪽부터 탐색을 진행하면 스택을 사용하는 장점이 사라졌다.

예를 들어 3 5 2 7이 있을 때 5의 오큰수는 7인 것을 찾았다면 이제 2의 오큰수를 찾아야하는데 탐색이 7까지 진행되어 다시 이전으로 돌아가야하는 문제가 생겼다.

 

따라서 오른쪽부터 탐색을 진행하였다. 가장 오른쪽에 있는 숫자는 무조건 -1이다. 

이후 계속해서 스택에 숫자를 넣고 스택의 top과 현재 수를 비교했을 때 스택의 top이 더 크다면 현재 숫자의 오큰수는 스택의 top이된다.

하지만 현재 숫자가 더 크다면 스택을 계속 pop하여 오큰수를 찾는다. 스택에는 현재 숫자에서 왼쪽부터 저장되어있기 때문에 큰 수를 찾았다면 종료하고 해당 수를 오큰수로 정한다.

 

구현

- 스택이 비어있다면 오큰수가 없다는 것이기 때문에 최종해에 -1을 추가하고

- 스택에 현재 숫자를 추가한다.

- 그리고 스택의 top과 현재 숫자를 비교한다.

- 스택의 top이 크다는 것은 현재 숫자의 오큰수이기 때문에 스택의 top을 최종해에 추가하고

- 현재 숫자를 스택에 넣는다.

- 스택의 top이 더 작다면 오큰수를 pop하면서 찾는다.

- while문을 통해 오큰수를 찾기위한 탐색을 완료했을 때 stack이 비게된다면 -1을 넣고 아니라면 스택의 top을 최종해에 추가한다.

for number in reversed(numbers):
    if stack:
        if stack[-1] > number:
            answer.append(stack[-1])
            stack.append(number)
        else:
            while stack and stack[-1] <= number:
                stack.pop()
            if stack:
                answer.append(stack[-1])
            else:
                answer.append(-1)
            stack.append(number)
    else:
        answer.append(-1)
        stack.append(number)

전체 코드

import sys
input = sys.stdin.readline

N = int(input())
numbers = list(map(int, input().split()))
stack = []
answer = []
for number in reversed(numbers):
    if stack:
        if stack[-1] > number:
            answer.append(stack[-1])
            stack.append(number)
        else:
            while stack and stack[-1] <= number:
                stack.pop()
            if stack:
                answer.append(stack[-1])
            else:
                answer.append(-1)
            stack.append(number)
    else:
        answer.append(-1)
        stack.append(number)

answer = list(reversed(answer))
print(*answer)

'알고리즘 풀이 > 백준' 카테고리의 다른 글

[백준 5002] 도어맨  (0) 2021.06.14
[백준 17299] 오등큰수  (0) 2021.06.14
[백준 6198] 옥상 정원 꾸미기  (0) 2021.06.11
[백준 2812] 크게 만들기  (0) 2021.06.11
[백준 17608] 막대기  (0) 2021.06.11