728x90
반응형
파라메트릭 서치(Parametric Search)는 최적화 문제를 결정 문제로 바꾸어 해결하는 방법입니다. 주어진 범위 내에서 특정 조건을 만족하는 값의 최대/최소를 찾기 위해 이분 탐색을 활용합니다.
이 기법은 주로 이분 탐색을 변형하여 사용하며, 시간 복잡도를 크게 줄일 수 있는 강력한 방법입니다.
1. 파라메트릭 서치의 핵심 아이디어
- 최적화 문제란?
- 어떤 값을 최대화하거나 최소화하는 문제를 의미.
- 예: "길이 x로 나누었을 때 가능한 가장 큰 값을 찾기", "시간을 최소화하는 경우".
- 결정 문제로 변환
- 주어진 조건을 만족하는지 '예/아니오(True/False)'로 판단하는 문제로 바꿉니다.
- 이 조건을 만족하는 값을 이분 탐색으로 찾아냅니다.
- 이분 탐색 활용
- 범위를 좁히며 조건을 만족하는 값의 최대/최소를 찾습니다.
- 결정 문제를 만족하면 범위를 조정하여 탐색을 계속 진행합니다.
2. 파라메트릭 서치의 기본 구성
1. 탐색 범위 설정
- 탐색할 값의 범위를 설정합니다. (예: 최소값 low, 최대값 high)
2. 조건 함수 정의
- 주어진 값을 만족하는지 판단하는 함수 is_valid(mid)를 정의합니다.
- 예: "길이 mid로 나누어 모두 만족하는가?", "시간 mid 이내에 가능한가?".
3. 이분 탐색 실행
- 조건 함수에 따라 탐색 범위를 줄여가며 답을 찾습니다.
3. 파라메트릭 서치의 일반적인 문제 유형
- 특정 조건을 만족하는 최대/최소 값 찾기
- 예: "가능한 가장 긴 랜선 길이", "최대 속도로 도달할 수 있는 거리".
- 최소 비용/최소 시간 문제
- 예: "최소 비용으로 특정 작업을 완수하기", "최소 시간 내에 모든 작업 완료".
- 특정 값을 만족하는 구간 나누기
- 예: "주어진 배열을 일정한 조건으로 나누었을 때 최대값 최소화".
4. 예제와 풀이
예제 1: 랜선 자르기 문제
문제:
- 길이가 다른 N개의 랜선이 주어지고, 이 랜선으로 K개의 동일한 길이의 랜선을 만들어야 합니다.
- 랜선의 최대 길이를 구하시오.
풀이:
- 탐색 범위 설정:
- 랜선의 길이는 최소 1에서 최대 max(랜선의 길이)까지 가능합니다.
- 조건 함수 정의:
- is_valid(mid): 길이가 mid인 랜선을 K개 이상 만들 수 있으면 True.
- 이분 탐색 실행:
- 탐색 범위를 줄여가며 조건을 만족하는 최대 길이를 찾습니다.
코드 구현
def is_valid(mid, arr, K):
count = sum(l // mid for l in arr)
return count >= K
def max_lan_length(arr, K):
low, high = 1, max(arr) # 랜선 길이의 최소, 최대 범위
result = 0
while low <= high:
mid = (low + high) // 2
if is_valid(mid, arr, K):
result = mid # 조건 만족 -> 길이를 더 늘려도 되는지 확인
low = mid + 1
else:
high = mid - 1 # 조건 불만족 -> 길이를 줄임
return result
# 테스트
arr = [802, 743, 457, 539] # 랜선 길이
K = 11 # 필요한 랜선 개수
print(max_lan_length(arr, K)) # 출력: 200
예제 2: 나무 자르기 문제
문제:
- N개의 나무가 주어지고, M미터 이상의 나무를 가져가기 위해 톱날을 조절해야 합니다.
- 나무를 자를 수 있는 톱날의 최대 높이를 구하시오.
풀이:
- 탐색 범위 설정:
- 톱날 높이는 최소 0에서 최대 max(나무 높이)까지 가능합니다.
- 조건 함수 정의:
- is_valid(mid): 톱날 높이가 mid일 때, 잘린 나무 길이 합이 M 이상인지 확인.
- 이분 탐색 실행:
- 탐색 범위를 줄여가며 조건을 만족하는 최대 톱날 높이를 찾습니다.
코드 구현
def is_valid(mid, trees, M):
total = sum(max(0, tree - mid) for tree in trees) # 잘린 나무 길이 합
return total >= M
def max_saw_height(trees, M):
low, high = 0, max(trees)
result = 0
while low <= high:
mid = (low + high) // 2
if is_valid(mid, trees, M):
result = mid # 조건 만족 -> 높이를 더 늘려도 되는지 확인
low = mid + 1
else:
high = mid - 1 # 조건 불만족 -> 높이를 줄임
return result
# 테스트
trees = [20, 15, 10, 17] # 나무 높이
M = 7 # 필요한 나무 길이
print(max_saw_height(trees, M)) # 출력: 15
5. 복잡도 분석
- 시간 복잡도:
- 이분 탐색은 범위를 절반씩 줄이므로 O(log(max_value)).
- 조건 함수는 배열을 순회하며 계산하므로 O(N).
- 따라서 전체 복잡도는 O(N × log(max_value)).
- 공간 복잡도:
- 조건 함수에서 추가적인 메모리를 사용하지 않으므로 O(1).
6. 정리
- 파라메트릭 서치의 주요 아이디어:
- "최적화 문제"를 "결정 문제"로 변환.
- 조건을 만족하는 값을 이분 탐색으로 탐색.
- 활용 사례:
- 최대/최소 값을 찾는 문제.
- 예: 랜선 자르기, 나무 자르기, 공장 배치, 최소 비용/최소 시간 문제.
- 구현 단계:
- 탐색 범위를 설정.
- 조건 함수(is_valid)를 정의.
- 이분 탐색을 통해 최적 값을 탐색.
'Category > Algorithm' 카테고리의 다른 글
| 우선순위 큐(Priority Queue)와 코딩 테스트 활용법 (3) | 2024.11.28 |
|---|---|
| 최장 증가 부분 수열(LIS, Longest Increasing Subsequence) (0) | 2024.11.28 |
| DP(다이나믹 프로그래밍, Dynamic Programming) (0) | 2024.11.22 |
| 다익스트라 알고리즘(Dijkstra's Algorithm) (0) | 2024.11.22 |
| 백트래킹(Backtracking) (0) | 2024.11.21 |