본문 바로가기
Baekjoon

17298번 오큰수(DP,Backtracking) Python

by juhongyee 2023. 5. 31.

동기

친구들이랑 같이 PS하다가 잘 못풀길래 저장해둡니다 :)

문제정의

입출력

간단한 생각 정리

먼저 오큰수 개념은 쉽네요. 오른쪽에 있는 나보다 큰 수중 제일 가까이 있는 수입니다.
이 때!
수 $A_1 A_2 ... A_iA_{i+1}...A_n$이 존재한다고 해봅시다. 일단 우리는 오큰수라는 개념을 생각할 때 Case들을 나눠볼 수 있겠죠.

$A_i$에 대해 생각해봅시다.
Case1. 만약 $A_{i+1}$이 $A_i$보다 크다면 당연히 $A_{i+1}$은 $A_i$의 오큰수입니다. Easy하네요.

Case2. 만약 $A_{i+1}$이 $A_i$보다 크지않다면? $A_{i+1}$의 오큰수가 $A_{i}$의 오큰수가 될 가능성이 있다 정도로 생각하면 되겠네요.  

 

만약 Case2.에서 $A_{i+1}$의 오큰수가 $A_k$라고 해봅시다.(-1일 수도 있겠죠.) 이 때 $A_i$의 오큰수가 $A_k$일 수도 있고 아닐 수도 있습니다. 만약 아니라고 해보죠. 그러면 다시 $A_k$의 오큰수를 볼 수 있습니다. $A_t$라고 해보죠.


또 작으면 또 그의 오큰수, 그의 오큰수를 본다고 생각합시다. 우리는 결국 -1이거나 $A_i$의 오큰수를 찾을 수 있을겁니다.

구현방법

위의 생각을 구현하려면 $A_i$의 오큰수를 구할 때 $A_{i+1}...A_n$까지의 모든 오큰수를 알고 있어야합니다.
그러면 이는 수학의 strong induction과 같은 것이고 DP로 구현할 수 있습니다.

그러면 뒤의 정보는 어떻게 알 수 있죠? 간단합니다. 뒤에서부터 반복문을 돌리면 됩니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 쉽죠? $A_n$의 오큰수는 -1입니다. 그다음엔 $A_{n-1}$,$A_{n-2}$들을 차례로 값을 구해주면 되겠습니다.

시간복잡도

위의 방법이 합리적인 방법일까요? worst case를 만들어 생각해보아야겠습니다.

$10 \ 9 \ 8\ 7\ 6\ 5\ 4\ 3\ 2\ 1$

위의 case는 worst case일까요? 아닙니다. 예를들어 10의 오큰수를 9로부터 가져올 때 9의 오큰수는 -1이므로 바로 -1로 가지게 됩니다.
다른 숫자도 그렇습니다.

$10 \ 1 \ 2\ 3\ 4\ 5\ 6\ 7\ 8\ 9 \ 10 \ 11$

요런경우는 어떨까요? $A_0$을 제외하고는 다 1번의 연산 $A_0$만 n번 연산입니다. 이때도 대충 2n번이면 연산이 끝나네요.

대체 어떻게 해야 worst case를 얻어낼 수 있을까요?

사실 잘 모르겠습니다. 운영체제 과제하러 가야해요...여백의 시간이 부족해서 남겨두겠습니다.
근데 거의 느낌상 $O(n)$입니다.
절대 $O(n^2)$은 안나올거라고 확신했고 잘 안돼도 $O(n\sqrt n)$일겁니다.

소스코드

import sys

N = int(input())

A = list(map(int,sys.stdin.readline().split()))

B = [0 for i in range(N)]

B[N-1] = (-1,-1)

for i in range(N-2,-1,-1):
    if(A[i]<A[i+1]):
        B[i] = (A[i+1],i+1)
    else:
        check = B[i+1]
        while(A[i]>=check[0] and not check[0] == -1):
            check = B[check[1]]

        B[i] = check

for idx,val in enumerate(B):
    print(val[0],end=' ')

'Baekjoon' 카테고리의 다른 글

백준 21909 Divisible by 3(Python)  (2) 2023.10.02
7578번 공장(Fenwick tree, python)  (0) 2023.07.08
1725번 히스토그램(Python,스택)  (0) 2023.06.05
1520번 내리막길(dps+dp)  (0) 2023.06.04
25823번 조합의 합의 합  (0) 2023.06.01