가장 긴 증가하는 부분 수열
- 가장 긴 증가하는 부분 수열(LIS, Longest Increasing Subsequence)은 대표적인 다이나믹 프로그래밍 문제이다.
- {10, 20, 10, 30, 20, 50} 과 같은 수열이 주어졌을 때, 수가 점점 증가하는 수열의 가장 긴 길이를 구한다.
1) Dynamic Programming 풀이법 - O(N^2)
- 파라미터 설명:
- n = 수열의 길이
- arr = 수열을 이루는 숫자가 담긴 배열
- d = arr[i]를 마지막 원소로 가질 때 LIS의 길이
- d[i] 값을 1로 초기화한다.
- 현재 위치(i)보다 이전에 위치한 원소(j)가 작은지 확인한다. (i는 기준이 되는 인덱스, j는 i보다 작은 인덱스)
- arr[i] > arr[j] 이면, 현재 위치 숫자 중 d의 최댓값을 구하고, 그 길이에 1을 더한다.
11053번: 가장 긴 증가하는 부분 수열
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이
www.acmicpc.net
n = int(input())
arr = list(map(int, input().split()))
d = [1] * n
for i in range(n): # 기준이 되는 인덱스
for j in range(i): # 이전에 있는 숫자들
# 현재 위치(i)보다 이전에 있는 원소(j)가 작은지 확인
if arr[i] > arr[j]:
d[i] = max(d[i], d[j]+1)
print(max(d))
2) Binary Search 풀이법 - O(NlogN)
d[i]를 구할 때 d[0] ~ d[i-1]의 최댓값을 미리 알고 있다면 이전의 모든 수를 확인할 필요가 없다.
→ N개의 원소에 대해 이진 탐색을 수행했기 때문에 시간복잡도는 O(NlogN)이다.
- d를 수열의 첫 번째 요소인 arr[0]으로 초기화한다.
- 현재 위치(i)가 이전 위치의 원소들보다 크면 d에 추가한다.
- 현재 위치(i)가 이전 위치보다 작거나 같으면, bisect_left()로 이전 위치의 원소 중 가장 큰 원소의 idx값을 구한다. d[idx] = arr[i]로 바꾼다.
12015번: 가장 긴 증가하는 부분 수열 2
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000,000)
www.acmicpc.net
from bisect import bisect_left
n = int(input())
arr = list(map(int, input().split()))
d = [arr[0]]
for i in range(n):
if arr[i] > d[-1]:
d.append(arr[i])
else:
idx = bisect_left(d, arr[i])
d[idx] = arr[i]
print(len(d))
'Algorithm > 개념 정리' 카테고리의 다른 글
[그래프] 서로소 집합으로 사이클 판별하기 (0) | 2022.08.19 |
---|---|
[그래프] 서로소 집합 (0) | 2022.08.19 |
[자료구조] 우선순위 큐 (heapq) (0) | 2022.08.13 |
[최단경로] 다익스트라 (0) | 2022.08.13 |