μ΄μ§νμ
μμ°¨ νμ vs μ΄μ§ νμ
ex) 리μ€νΈμμ 12μΈ μμμ μμΉ μ°ΎκΈ°
μμ°¨ νμ
리μ€νΈ μμ μλ νΉμ ν λ°μ΄ν°λ₯Ό μ°ΎκΈ° μν΄ μμμλΆν° νλμ© νμΈ → μκ°λ³΅μ‘λ: O(N)

μ΄μ§ νμ
μ λ ¬λμ΄ μλ 리μ€νΈμμ νμ λ²μλ₯Ό μ λ°μ© μ’νκ°λ©° λ°μ΄ν° νμ → μκ°λ³΅μ‘λ: O(logN)

- μ΄μ§νμ μνν λ μμμ (left)μ λμ (end)μ κΈ°μ€μΌλ‘ νμ λ²μ λͺ μ
- κ° λ¨κ³λ§λ€ νμ λ²μλ₯Ό 2λ‘ λλκΈ°
- μ΄μμ μΈ κ²½μ° λ§€ λ¨κ³λ§λ€ λ²μκ° λ°μΌλ‘ κ°μ → log 볡μ‘λλ₯Ό κ°μ§
- λνμ μΈ μ¬λ‘
- λ§€μ° λμ(μ΅ λ¨μ μ΄μ) νμ λ²μμμ μ΅μ μ ν΄λ₯Ό μ°ΎμμΌ νλ κ²½μ°
- λ°μ΄ν°λ₯Ό μ λ ¬ν λ€μ λ€μμ 쿼리(query)λ₯Ό λ λ €μΌ νλ κ²½μ°
μ΄μ§ νμ μ½λ
μ΄μ§ νμμ λ°°μ΄μ΄ μ λ ¬λμ΄μλ€λ κ°μ νμ μν
1. μ¬κ·ν¨μ μ΄μ©
function binarySearch(arr, target, start, end) {
if (start > end) return -1; // λ²μ λμ κ²½μ°
let mid = parseInt((start + end) / 2);
if (arr[mid] === target)
return mid; // μ°Ύμ κ²½μ° μ€κ° μΈλ±μ€ λ°ν
else if (arr[mid] > target)
return binarySearch(arr, target, start, mid - 1); // μ€κ° μΈλ±μ€ κ°λ³΄λ€ target κ°μ΄ μμ κ²½μ° μΌμͺ½ νμ
else return binarySearch(arr, target, mid + 1, end); // μ€κ° μΈλ±μ€ κ°λ³΄λ€ target κ°μ΄ λ ν° κ²½μ° μ€λ₯Έμͺ½ νμ
}
2. λ°λ³΅λ¬Έ μ΄μ©
function binarySearch(arr, target, start, end) {
while (start <= end) {
let mid = parseInt((start + end) / 2);
if (arr[mid] === target)
return mid; // μ°Ύμ κ²½μ° μ€κ° μΈλ±μ€ λ°ν
else if (arr[mid] > target)
end = mid - 1; // μ€κ° μΈλ±μ€ κ°λ³΄λ€ target κ°μ΄ μμ κ²½μ° μΌμͺ½ νμ
else start = mid + 1; // μ€κ° μΈλ±μ€ κ°λ³΄λ€ target κ°μ΄ λ ν° κ²½μ° μ€λ₯Έμͺ½ νμ
}
return -1; // κ°μ μ°Ύμ§ λͺ»ν κ²½μ° -1 리ν΄
}
μ λ ¬λ λ°°μ΄μμ νΉμ μμ κ°μ ꡬνκΈ°
μ½λ© ν μ€νΈμμ μ λ ¬λ λ°°μ΄μμ νΉμ λ²μμ ν΄λΉνλ μμμ κ°μλ₯Ό κ³μ°νλ λ¬Έμ μ’ μ’ μ‘΄μ¬
→ lowerBound() ν¨μμ upperBound() ν¨μ μ¬μ©

lowerBound(arr, x)
μ λ ¬λ μμλ₯Ό μ μ§νλ©΄μ λ°°μ΄ arrμ xλ₯Ό λ£μ κ°μ₯ μΌμͺ½ μΈλ±μ€ λ°ν
function lowerBound(arr, target, start, end) {
while (start < end) {
const mid = parseInt((start + end) / 2);
if (arr[mid] >= target)
end = mid; // μ΅λν μΌμͺ½μΌλ‘ μ΄λ
else start = mid + 1;
}
return end;
}
upperBound(arr, x)
μ λ ¬λ μμλ₯Ό μ μ§νλ©΄μ λ°°μ΄ arrμ xλ₯Ό λ£μ κ°μ₯ μ€λ₯Έμͺ½ μΈλ±μ€ λ°ν
function upperBound(arr, target, start, end) {
while (start < end) {
const mid = parseInt((start + end) / 2);
if (arr[mid] > target) end = mid;
else start = mid + 1; // μ΅λν μ€λ₯Έμͺ½μΌλ‘ μ΄λ
}
return end;
}
countByRange()
μ λ ¬λ λ°°μ΄μμ κ°μ΄ νΉμ λ²μμ μνλ μμμ κ°μ κ³μ°
function countByRange(arr, leftValue, rightValue) {
let rightIndex = upperBound(arr, rightValue, 0, arr.length);
let leftIndex = lowerBound(arr, leftValue, 0, arr.length);
return rightIndex - leftIndex;
}
// λ°°μ΄ μ μΈ
let arr = [1, 2, 3, 3, 3, 3, 4, 4, 8, 9];
// κ°μ΄ 4μΈ λ°μ΄ν° κ°μ μΆλ ₯
console.log(countByRange(arr, 4, 4));
// κ°μ΄ [-1, 3] λ²μμ μλ λ°μ΄ν° κ°μ μΆλ ₯
console.log(countByRange(arr, -1, 3));
ννΈλ©νΈλ¦ μμΉ
μ΄μ§ νμ 쑰건: λ³κ²½ν (μ΅μ νν ) κ° xμ λν΄ f(x)κ° λ¨μ‘° μ¦κ° νΉμ λ¨μ‘° κ°μ
- λ¨μ‘° μ¦κ° ν¨μ: x β¦ y μ΄λ©΄ f(x) β¦ f(y)μΈ κ²½μ° → κ³λ¨ νμ νΉμ μΌμͺ½λ³΄λ€ μ€λ₯Έμͺ½ κ°μ΄ λ νΌ

μ κ·Ό λ°©λ²
μ΅μ ν λ¬Έμ λ₯Ό κ²°μ λ¬Έμ (μ/μλμ€)λ‘ λ°κΎΈμ΄ ν΄κ²°νλ λ°©λ²
ex) νΉμ ν 쑰건μ λ§μ‘±νλ κ°μ₯ μλ§μ κ°μ λΉ λ₯΄κ² μ°Ύλ μ΅μ ν λ¬Έμ
- νλΌλ©νΈλ¦ μμΉ λ¬Έμ λ μ΄μ§ νμ μ΄μ©ν΄μ ν΄κ²° κ°λ₯