문제

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


풀이


풀이1

  • 255784 KB, 596 ms(Pypy), 155584 KB, 1092 ms (Python)
import sys
input = sys.stdin.readline

N = int(input().rstrip()) # 수열 A 의 길이 N
A = list(map(int, input().rstrip().split())) # 수열 A
stack = []
NGE = [-1] * N

for i in range(N - 1, -1, -1) :
    while stack and stack[-1] <= A[-1] :
        stack.pop()

    if stack : NGE[i] = stack[-1]
    stack.append(A.pop())

print(*NGE)


풀이1 설명

스택문제는 누가봐도 짝 맞추기인 문제가 아니면 풀이 떠올리기가 아직 좀 어렵다..

1. 문제의 조건

시간 제한 1초인데 N의 범위가 1,000,000 → O(N^2)로 풀면 안된다 (for문 두번 돌리면 안된다)

→ 스택, 큐 …

2. 정답을 어떤 방향으로 찾을 것인가?

1) NGE[-1]은 무조건 -1(가장 오른쪽이므로)

2) 오른쪽에 있는 수를 기준으로 찾으므로, 찾는 범위를 점점 늘려갈 수 있도록 (dp처럼)

(그리고 왼쪽부터 구하면 최악의 경우에는 처음부터 전체를 다 확인해봐야할 수 있다)

→ 오른쪽 부터 찾자 !

3. 예제 풀어보기

수열 A stack 정답 설명
3 5 2 7   -1 -1 -1 -1 초기 상태
3 5 2 7 -1 -1 -1 -1 A[-1]인 7의 NGE를 구함
- len(stack) == 0 이므로 NGE는 -1
- 확인한 A[-1]을 pop하고 stack에 append (NGE 후보)
3 5 7 2 -1 -1 7 -1 A[-1]인 2의 NGE를 구함
- stack[-1]인 7보다 2가 작음. 따라서 NGE는 7
- 확인한 A[-1]을 pop하고 stack에 append (NGE 후보)
3 7 ~2~ 5 -1 7 7 -1 A[-1]인 5의 NGE를 구함
- stack[-1]인 2보다 5가 작지 않음
- 2는 더 이상 다른 수의 NGE가 될 수 없으므로 pop한다.
(stack[-1]이 A[-1]보다 클 때까지 stack을 pop)
(왜냐하면 2가 NGE려면 2보다 작은 수가 나와야하는데(ex. 1), 이 수의 NGE는 2보다 더 왼쪽에 있는 수인 5가 될 것임)
- stack[-1]인 7보다 5가 작음. 따라서 NGE는 5
- 확인한 A[-1]를 pop하고 stack에 append (NGE 후보)
  7 5 3 5 7 7 -1 A[-1]인 3의 NGE를 구함
- stack[-1]인 5보다 3가 작음. 따라서 NGE는 5
- 확인한 A[-1]을 pop하고 stack에 append (NGE 후보)

예제에서 확인한 규칙에 따라 풀이를 작성


풀이2

import sys
input = sys.stdin.readline

N = int(input().rstrip()) # 수열 A 의 길이 N
A = list(map(int, input().rstrip().split())) # 수열 A
stack = [0]
NGE = [-1] * N

for i in range(1, N) :
    while stack and A[stack[-1]] < A[i] :
        NGE[stack.pop()] = A[i]

    stack.append(i)

print(*NGE)


풀이2 설명

  1. stack에는 NGE를 구해야하는 요소의 인덱스를 담음
  2. 무조건 연속한 두 요소만을 비교 (index i, i +1을 비교하여 i의 NGE 구함)
    1. A[i] < A[i+1]이면 stack을 pop (stack에  i 있음). A[i]의 오큰수는 A[i+1]
    2. 그렇지 않은 경우, stack은 유지 (i가 stack에 있는 상태). 이후에 찾은 A[i+1]의 오큰수는 A[i]의 오큰수가 될 수도 있음

이와 같은 규칙으로 코드 작성


Leave a comment