2 minute read

사용언어

Visual studio 2019 C++

유형

다이나믹 프로그래밍 - LIS(최장증가수열)


https://leleluv1122.github.io/algorithm/LIS/ 의 2탄으로…
저번에 설명했던 LIS는 10만 이하의 수에서 시간초과가 나지않은 풀이였다.

이번에는 10만이 넘어갈때에 풀이를 설명하고자 한다.
먼저, lower_bound를 알아야 한다.

lower_bound

  • lower_bound는 #include <algorithm> 에 포함되어있는 함수이다.
  • 이진탐색(Binary Search)기반의 탐색 방법이다.
  • 찾으려는 key값이 없으면 key값보다 큰 가장 작은 정수의 값을 찾음.

LIS의 크기만을 구할때에는 밑의 풀이를 사용한다.

배열 LIS 풀이

int dp[10];
int arr[9] = { 0, 1, 6, 2, 5, 7, 3, 5, 6 }; // 0은 포함하지 않음

int len = 1;
dp[1] = arr[1];

for (int i = 1; i < 9; i++) {
	if (dp[len] < arr[i]) {
		dp[++len] = arr[i];
		continue;
	}

	int idx = lower_bound(dp + 1, dp + len + 1, arr[i]) - dp;
	dp[idx] = arr[i];
}

cout << len << endl;

vector LIS 풀이

vector<int> dp;
vector<int> v;
int arr[8] = {1, 6, 2, 5, 7, 3, 5, 6 };

for (int i = 0; i < 8; i++)
	v.push_back(arr[i]);
	
dp.push_back(v[0]);

for (int i = 1; i < 8; i++) {
	if (dp.back() < v[i]) {
		dp.push_back(v[i]);
		continue;
	}

	auto it = lower_bound(dp.begin(), dp.end(), v[i]);
	*it = v[i];
}

cout << dp.size() << endl;

이렇게 하면 N의 개수가 10만이 넘어가도 시간초과가 나지않게 풀이를 작성할 수 있다.


백준 LIS + lower_bound 문제 (LIS의 size를 구하는문제)

사이즈를 구할때에는 위와같은 방식으로 풀면되지만, 배열까지 구할 경우 추가해야 되는 부분이 있다.

vector<int> dp;
vector<int> v;
stack<int> ans;
int p[MAX]; // MAX는 각 문제의 max값을 define이나 const를 사용하여 정의하면 된다.
int arr[8] = {1, 6, 2, 5, 7, 3, 5, 6 }; // 임의의 수

for (int i = 0; i < 8; i++)
	v.push_back(arr[i]);
	
dp.push_back(v[0]);
p[0] = dp.size() - 1;

for (int i = 1; i < 8; i++) {
	if (dp.back() < v[i]) {
		dp.push_back(v[i]);
		p[i] = dp.size() - 1; // p[i]에 lis의 크기를 넣어놓음
		continue;
	}

	auto it = lower_bound(dp.begin(), dp.end(), v[i]);
	*it = v[i];
	p[i] = it - dp.begin(); // it의 자리의 값이 변경될 경우 p[i]의 값을 it자리값으로 바꿔줌
}

int cnt = dp.size() - 1;
for(int i = 7; i >= 0; i--) {
	if(cnt == p[i]) { // cnt가 lis크기 넣어놓은 값과 같게되면 그 값이 LIS값이므로 push
		ans.push(v[i]); 
		cnt--;
		// 위에서부터 내려오기때문에 stack을 사용해서 
		// 값을 출력할때에는 정방향으로 출력할 수 있게한다.
	}
}

cout << ans.size() << endl;
while(!ans.empty()) {
	cout << ans.top() << " ";
	ans.pop();
}
cout << endl;

백준 LIS + lower_bound 문제 (LIS의 사이즈와 배열을 둘다 구하는문제)

14002번 문제와 14003문제는 배열의 크기의 차이가 존재하지만 lower_bound로 풀 경우 풀이가 같게된다.

Categories:

Updated:

Comments