Odds and Ends

백준 문제 : 가장 긴 증가하는 부분 수열(LIS) [Dynamic Programming /Binary Search, 실버 2단계, python] 본문

코딩 테스트

백준 문제 : 가장 긴 증가하는 부분 수열(LIS) [Dynamic Programming /Binary Search, 실버 2단계, python]

Squidward 2022. 6. 5. 02:22

문제

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

출력

첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.

문제풀이

수열이 주어졌다.

수열에서 몇 개의 수를 순서를 유지한채 뽑았을 때(부분 수열), 뽑은 수들이 증가하도록 하고 싶다.

이때 가장 많이 뽑을 수 있는 수의 개수를 구한다.

ex) 5 2 5 3 4 1 6 -> 이 수열에서 순서를 유지하며 증가하게 부분 수열을 만들었을 때 -> [1,6], [2,3,4,6] ... 등등

 

이때 증가하는 부분 수열은 (1,2,5) 마지막 원소를 제외해도 (1,2) 증가하는 부분 수열이다.

여기서 마지막 원소 (5)를 붙인다면 5보다 앞에있고, 5보다 작은 수로 끝나는 가장 긴 부분 수열에 붙인다.

즉, 지금까지 만들어놓은 증가수열에 수를 추가하려면,

만들어놓은 증가 수열이 추가하려는 수보다 앞에 있어야하고,

마지막 수가 추가하려는 수보다 작아야한다.

 

 

정답 코드 - 2가지 유형

 

[다이나믹 프로그래밍 유형으로 풀기]

 

x = 수열 A의 크기

arr = 수열 A를 이루고 있는 A(i)를 담은 배열

dp = arr[i]를 마지막 원소로 가질 때 가장 긴 증가하는 부분 수열의 길이

x = int(input())

arr = list(map(int, input().split()))

dp = [1 for i in range(x)] # 1로 초기화 하는 이유: 첫 시작으로 어떤 수를 넣든 수열길이가 1이됨

# i가 증가하는 순서대로 
for i in range(x):
    for j in range(i):
        if arr[i] > arr[j]:
            dp[i] = max(dp[i], dp[j]+1) # +1인 이유: j까지 온 가장 긴 부분수열에서 하나를 더 추가해서

print(max(dp))

1. dp[i]의 값을 1로 초기화

2. 현재 위치(i)보다 이전에 있는 원소(j)가 작은지 확인한다. (크거나 같으면 가장 긴 증가하는 부분 수열이 될 수 없음)

3. 작다면, 현재 위치의 이전 숫자 중, dp 최댓값을 구하고 그 길이에 1을 더해주면 된다.

 

이분 탐색

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

 

14002번: 가장 긴 증가하는 부분 수열 4

수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이

www.acmicpc.net

또 다른 문제임. 문제와 입/출력 결과값 똑같지만 이분탐색으로 품. 골드 4단계

import bisect

x = int(input())
arr = list(map(int, input().split()))

dp = [arr[0]]

for i in range(x):
    if arr[i] > dp[-1]:
        dp.append(arr[i])
    else:
        idx = bisect.bisect_left(dp, arr[i])
        dp[idx] = arr[i]

print(len(dp))

 

 

 

https://www.youtube.com/watch?v=sYh62pujaH8 << 강의 들으며 이해 및 참고

 

 

 

 

728x90