[알고리즘] 상한가, 하한가 구하기 (이진 탐색 활용)
by mini_min상한가,하한가 구하기
💡 이진 탐색으로 상한가와 하한가를 구해서 원하는 숫자를 출력하자.
- 백준 10816번-
- ‘중복 원수의 개수’ 를 알아내고 싶을 때, 중복 원소의 왼쪽 끝과 오른쪽 끝의 인덱스를 알아내서 계산하면 된다.
- 이진 탐색 개념을 이용하기에 배열은 사전 정렬 되어있어야 한다.
방법
- 찾으려는 값의 하한선, 상한선을 따로 구할 생각을 하자.
- 하한선은 찾으려는 값 이상의 값이 나타난 위치다.
- “이상” 이란 같거나 큰 수를 뜻한다.
- 상한선은 찾으려는 값의 초과 값이 나타난 위치다.
- “초과” 란 보다 큰 수를 뜻한다.
상한가, 하한가 예시
- 정렬된 배열에서 ‘숫자 10의 상한가, 하한가를 찾는다.
- (하한선은 최초 10 이 나오는 위치인 3, 상한선은 10을 넘어서는 최초 위치 6 이 나와야 한다.)
2 | 3 | 5 | 10 | 10 | 10 | 12 | 16 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
💡 검색 범위가 절 반만큼 줄어드는 이진 탐색을 이용해서 하한가와 상한가가 되는 마지노선을 찾아서 반환한다.
- 하한가 찾기 → 상한선을 중간 위치만큼 내리면서 왼쪽으로 범위를 좁힌다.
- 하한가, 가장 처음 값을 찾기 위해서는 하한선(low)가 아닌 상한선(high)이 줄어들면서 찾아야 한다.
- 즉, 중간 값이 <<같거나 큰 값>>에 해당되면 상한선 high 가 왼쪽으로 ← 이동(작아진다고)한다고 단순하게 생각하기!!
private static int lowerBound(int[] arr, int key) {
int lo = 0;
int hi = arr.length;
// lo가 hi랑 같아질 때 까지 반복
while (lo < hi) {
int mid = (lo + hi) / 2; // 중간위치를 구한다.
/*
* key 값이 중간 위치의 값보다 작거나 같을 경우
*
* (중복 원소에 대해 왼쪽으로 탐색하도록 상계를 내린다.)
*/
if (key <= arr[mid]) {
hi = mid;
}
//찾는 값이 중간 값 보다 크기 때문에, 범위를 중앙+1값으로 다시 줄어버림
else {
lo = mid + 1;
}
}
return lo;
}
- 상한가 찾기 → 반대로 하한선을 올리면서 오른쪽으로 범위를 줄인다.
- 상한가, 찾는 값보다 큰 값을 찾기 위해서는 하한선이 올라가면서 가장 차이가 없는 큰 값을 찾으면 된다.
- 중간 값이 <<찾는 값보다 큰 값>>에 해당되면 하한선이 중간 값만큼 → 바짝 따라 올라온다고 생각하기.
private static int UpperBound(int[] arr, int key) {
int lo = 0;
int hi = arr.length;
// lo가 hi랑 같아질 때 까지 반복
while (lo < hi) {
int mid = (lo + hi) / 2; // 중간위치를 구한다.
/*
* key 값이 중간 위치의 값보다 작거나 같을 경우
*
* (중복 원소에 대해 왼쪽으로 탐색하도록 상계를 내린다.)
*/
if (key < arr[mid]) {
hi = mid;
}
//찾는 값이 중간 값 보다 크기 때문에, 범위를 중앙+1값으로 다시 줄어버림
else {
lo = mid + 1;
}
}
return lo;
}
'매일매일 알고리즘 공부 > 알고리즘 개념' 카테고리의 다른 글
[알고리즘] 에라토스테네스의 체 란? (Prime 소수 구하기) (0) | 2023.09.22 |
---|---|
[알고리즘] 유클리드 호제법 (GCD) (0) | 2023.08.29 |
[알고리즘] 계수 정렬 (Counting sort) 개념 + 백준 10989번 예제 (0) | 2023.08.17 |
[알고리즘] 이진 탐색 개념 + 예제 (0) | 2023.08.16 |
[알고리즘] 비트마스킹(BitMasking) 이란? (0) | 2023.07.25 |
블로그의 정보
개발자 미니민의 개발로그
mini_min