[최장 증가 부분 수열(LIS)]
최장 증가 부분 수열(Longest increasing subsequence) 알고리즘은 주어진 수열에서 제일 길게(=최장) 증가하는 부분적인 수열을 의미합니다.
문제를 해결할 수 있는 방법은 다양하지만, 보통 DP(동적 프로그래밍)와 Binary Search(이분 탐색)를 사용합니다.
DP는 이중 for문을 사용하므로 시간복잡도가 O(n^2)이고 Binary Search는 O(nlogn) 시간복잡도를 가집니다. 그렇기 때문에 DP로 구현하지 않고 Binary Search로 구현하는 감각을 익혀야 합니다!
최장 증가 부분 수열 알고리즘으로 문제를 풀 수 있다는 가정 하에, Binary Search로 구현하면 n의 범위에 상관없이 해결할 수 있기 때문입니다.
[DP를 활용한 접근]
파이썬을 사용한다면 LIS 알고리즘을 쉽게 구현할 수 있습니다. 만약, C++이나 swift 언어를 사용할 경우에는 binary search를 직접 구현했어야 했는데 말이죠... 너무 좋은 언어인 거 같습니다ㅋㅋㅋ
import sys, bisect
n = int(sys.stdin.readline().rstrip())
arr = list(map(int,sys.stdin.readline().rstrip().split()))
dp = [arr[0]]
for i in range(n):
if(arr[i] > dp[-1]):
dp.append(arr[i])
else:
idx = bisect.bisect_left(dp,arr[i])
dp[idx] = arr[i]
print(len(dp))
📌 배열의 길이를 입력받는다.
📌 배열을 입력받는다.
📌 각 배열의 요소를 순회하면서 dp 배열에 저장된 마지막 원소보다 크다면 dp에 추가한다.
📌 크지 않다면 해당 요소가 들어갈 위치를 binary serach로 찾아서 업데이트한다.
알고리즘 문제를 푸는데 아래와 같은 케이스에서 LIS 알고리즘을 생각해낼 수 있으면 됩니다.
첫 번째!! 정해진 기간동안 부분적으로 증가하거나 감소하는 길이를 찾으라는 개념이 있을 경우
두 번째!! 아래 그림과 같이 무언가 꼬인 선들이 존재하는 경우
[문제를 통한 감각 익히기]
알고리즘을 공부하면 그 알고리즘에 대한 문제를 집중적으로 푸는 것이 좋다고 생각해서 풀어보시는 걸 추천드립니다 ✨
https://www.acmicpc.net/problem/3745
https://www.acmicpc.net/problem/1365
https://www.acmicpc.net/problem/2352
https://www.acmicpc.net/problem/1818
https://www.acmicpc.net/problem/18353
https://www.acmicpc.net/problem/12014
https://www.acmicpc.net/problem/3066