더 이상 tistory 블로그를 운영하지 않습니다. glanceyes.github.io에서 새롭게 시작합니다.

새소식

알고리즘/개념 정리

가장 긴 증가하는 부분 수열 Longest Increasing Subsequence(LIS)

  • -

 

개인적으로 알고리즘은 즉각적으로 바로 구현할 수 있도록 몸에 베어야 하되 복습하는 데 너무나 많은 시간을 투자해서는 안 되고, 문제를 풀면서 실전으로 익혀야 한다고 생각한다. 학기가 시작되면서 바빠진 만큼 지난 잊힌 알고리즘 개념들을 핵심과 코드만 짧게 정리하여 평소에도 자주 보면서 익숙해지고자 한다. 기본적으로 코드는 특별한 설명이 없으면 C++를 기반으로 한다.

 

 

가장 긴 증가하는 부분 수열 Longest Increasing Subsequence(LIS)

 

정의

주어진 sequence의 모든 부분 수열(subsequence) 중 오름차순으로 정렬된 가장 긴 수열

 

문제

길이가 $N$인 임의의 수열 A의 Longest Increasing Subsequence(LIS) 길이를 구해보자.

 

방법

시간복잡도에 따라서는 크게 두 가지로, 구분할 수 있고, 사용하는 자료구조의 관점에서는 크게 세 가지 방법으로 요약할 수 있다.

 

1. 동적 계획법(DP)

(1) $O(N^2)$ 알고리즘

(2) 다음과 같은 메모이제이션 배열을 정의한다.

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

(3) A[i]가 어떤 증가하는 부분 수열의 마지막 원소가 되기 위해서는 A[i]가 추가되기 전에 증가하는 부분 수열의 마지막 원소가 A[i]보다 작아야 한다.

 

반복적 동적 계획법

for (int i = 0; i < n; i++){
	dp[i] = 1;
    for (int j = 0; j < i; j++){
    	if (a[i] > a[j] && dp[i] < dp[j] + 1){
        	dp[i] = dp[j] + 1;
        }
    }
}

 

재귀적 동적 계획법

cache[i]: a[i]에서 시작하는 가장 긴 증가하는 부분 수열의 길이
int go(int start){
	int& ret = cache[start];
    
    if (ret != -1){
    	return ret;
    }
    
    ret = 1; 
    
    for (int i = start + 1; i < n; i++){
    	if (a[start] < a[i]){
        	ret = max(ret, go(i) + 1);
        }
    }
    
	return ret;
}

 

 

2. Binary Search

(1) $O(N \log N)$ 알고리즘

(2) 다음과 같은 배열을 사용한다.

s[i]: 길이가 i+1인 LIS 중에서 마지막 원소로 올 수 있는 가장 작은 수

(3) 앞에서 최대한 작은 수들로 LIS가 구성되어야 뒤에서 더 많은 수들로 더 긴 LIS를 형성할 가능성이 있으므로 lower_bound 사용

s.push_back(a[0]);

for (int i = 0; i < n; i++){
	auto iter = lower_bound(s.begin(), s.end(), a[i]);
    if (iter >= s.end()){
    	s.push_back(a[i]);
    }
    else {
    	*iter = a[i];
    }
}

printf("%d\n", s.size()); // LIS의 길이 출력

 

 

3. Segment Tree

(1) $O(N \log N)$ 알고리즘

(2) 다음과 같은 세그먼트 트리의 leaf에 대응되는 배열을 사용한다.

d[i]: a[i]를 마지막 원소로 가지는 가장 긴 증가하는 부분 수열의 길이

(3) 0번째부터 $N-1$번째 원소까지 loop를 실행하면서 매번 a[i]보다 작은 배열 d의 원소들 값 중에서 최댓값을 query로 구하고, d[i] = (찾은 최댓값) + 1로 계산한다.

 

 

Contents

글 주소를 복사했습니다

부족한 글 끝까지 읽어주셔서 감사합니다.
보충할 내용이 있으면 언제든지 댓글 남겨주세요.