백준 11053번 가장 긴 증가하는 부분 수열 문제 풀이: 이진 탐색 알고리즘을 활용하여 주어진 수열에서 가장 긴 증가하는 부분 수열의 길이를 구하는 방법을 상세하게 설명합니다. 문제 출처부터 풀이, 코드 구현까지의 과정을 살펴봅니다.
1. 문제출처: https://www.acmicpc.net/problem/11053
11053번: 가장 긴 증가하는 부분 수열
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이
www.acmicpc.net
2. 문제풀이
이진 탐색(Binary Search)을 사용한 O(N log N) 시간 복잡도의 풀이 방법입니다.
다이나믹 프로그래밍(DP)로도 풀 수 있습니다.
// key값 이상인 수 중에서 가장 먼저 나온 수의 인덱스를 반환
int mylower_bound(vector<int>& arr, int key) {
int st = 0;
int ed = arr.size() - 1;
while (ed > st) {
int mid = (st + ed) / 2;
if (key > arr[mid]) {
st = mid + 1;
}
else {
ed = mid;
}
}
return ed;
}
이 함수는 key 값 이상인 수 중 첫 번째로 나오는 수의 인덱스를 찾는 이진 탐색 함수입니다.
st는 검색 시작 인덱스, ed는 검색 끝 인덱스입니다.
이진 탐색으로 key 값 이상의 첫 번째 수의 인덱스를 찾아서 반환합니다.
void solve() {
int cnt = 1;
res.push_back(arr[0]);
for (int i = 1; i < N; i++) {
if (res.back() < arr[i]) {
res.push_back(arr[i]);
cnt++;
}
else {
int idx = mylower_bound(res, arr[i]);
res[idx] = arr[i];
}
}
cout << cnt;
}
이 함수는 가장 긴 증가하는 부분 수열의 길이를 계산하고 출력하는 함수입니다.
cnt는 가장 긴 증가하는 부분 수열의 길이를 저장하는 변수이고, res 벡터에 수열 arr의 첫 번째 원소를 추가합니다.
for문을 통해 수열 arr의 모든 원소를 순회하며, res 벡터의 마지막 원소보다 크면 res 벡터에 추가합니다.
그렇지 않으면, mylower_bound를 호출해 key 값이상의 수를 찾아 해당 위치의 값을 현재 원소로 바꾸어 줍니다.
최종 계산된 가장 긴 증가하는 부분 수열의 길이(cnt)를 출력합니다.
3. 문제코드
#include <iostream>
#include <vector>
using namespace std;
int N;
vector<int> arr, res;
// key값 이상인 수 중에서 가장 먼저 나온 수의 인덱스를 반환
int mylower_bound(vector<int>& arr, int key) {
int st = 0;
int ed = arr.size() - 1;
while (ed > st) {
int mid = (st + ed) / 2;
if (key > arr[mid]) {
st = mid + 1;
}
else {
ed = mid;
}
}
return ed;
}
void solve() {
int cnt = 1;
res.push_back(arr[0]);
for (int i = 1; i < N; i++) {
if (res.back() < arr[i]) {
res.push_back(arr[i]);
cnt++;
}
else {
int idx = mylower_bound(res, arr[i]);
res[idx] = arr[i];
}
}
cout << cnt;
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
cin >> N;
arr.resize(N + 1);
for (int i = 0; i < N; i++) {
cin >> arr[i];
}
solve();
}
이진 탐색 알고리즘을 활용하여 주어진 수열에서 가장 긴 증가하는 부분 수열의 길이를 찾는 방법을 설명하였습니다. 문제 이해부터 코드 구현까지의 과정을 따라가면서 논리적으로 문제를 해결하는 능력을 키웠기를 바랍니다.
'C++' 카테고리의 다른 글
[백준/C++]11727번 - 2×n 타일링 2 (0) | 2023.07.23 |
---|---|
[백준/C++]1932번 - 정수 삼각형 (1) | 2023.07.21 |
[백준/C++]2579번 - 계단 오르기 (0) | 2023.07.20 |
[백준/C++]1149번 - RGB거리 (0) | 2023.07.19 |
[백준/C++]11726번 - 2×n 타일링 (0) | 2023.07.19 |