CS β find vs binary search
π 05/05 β std::find vs std::binary_search (μ ν νμ vs μ΄λΆ νμ)
λͺ¨μλ©΄μ μ£Όμ : βstd::find()μ std::binary_search()μ μ°¨μ΄μ μ λν΄μ μ€λͺ ν΄ μ£ΌμΈμβ μ λ ¬ μ μ β μκ°λ³΅μ‘λ β λ°ν νμ μ°¨μ΄ β lower_boundΒ·equal_range β set/map λ©€λ² ν¨μ vs μκ³ λ¦¬μ¦ κΌ¬λ¦¬μ§λ¬Έ μ°κ²° λ€λ¦¬
νμ΅ μμ μ νμ β 컨ν μ΄λμμ μκ³ λ¦¬μ¦μΌλ‘
13~16λ²μμ STL 컨ν
μ΄λ μ λ°(μνμ€Β·μ°κ΄Β·λΉμμΒ·μ΄λν°)μ μ 리νλ€λ©΄, 17λ²λΆν°λ κ·Έ μμμ λμνλ <algorithm> ν€λμ νμ ν¨μλ₯Ό λ€λ£Ήλλ€.
1
2
3
4
13~16λ² STL 컨ν
μ΄λ β μλ£κ΅¬μ‘° (μ΄λμ λ΄μκΉ)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
17λ² std::find vs std::binary_search β
β μκ³ λ¦¬μ¦ (μ΄λ»κ² μ°ΎμκΉ)
μ΄ν sort / lower_bound / equal_range β μ λ ¬Β·λ²μ μκ³ λ¦¬μ¦ family
μ΄ μ£Όμ λ λ©΄μ μμ βλ ν¨μμ μ°¨μ΄λ?β μμΌλ‘ μ’κ² λ€μ΄μλ κ²°κ΅ (1) μ λ ¬ μ μ β (2) μκ°λ³΅μ‘λ β (3) λ°ν νμ μ°¨μ΄ β (4) λ λμ λμ(lower_bound) β (5) set/map λ©€λ² ν¨μμμ λΉκ΅λ‘ νΌμ³μ§λλ€. λ¨μν βμ ν vs μ΄λΆβμ΄λΌκ³ λ§ λ΅νλ©΄ 꼬리μ§λ¬Έμμ λ§νλλ€.
λͺ¨μλ©΄μ λ΅λ³
std::findμ std::binary_searchλ λ λ€ <algorithm> ν€λμ νμ ν¨μμ§λ§ μ μ 쑰건과 μκ°λ³΅μ‘λ, λ°ν νμ
μ΄ λͺ¨λ λ€λ¦
λλ€.
std::findλ μ ν νμμ
λλ€. [first, last) ꡬκ°μ μ²μλΆν° λκΉμ§ μννλ©΄μ == μ°μ°μλ‘ κ°μ λΉκ΅νκ³ , μΌμΉνλ 첫 μμμ iteratorλ₯Ό λ°νν©λλ€. λͺ» μ°ΎμΌλ©΄ lastλ₯Ό λ°νν©λλ€. μκ°λ³΅μ‘λλ O(n)μ΄κ³ 컨ν
μ΄λκ° μ λ ¬λΌ μμ νμκ° μμΌλ©°, vectorΒ·listΒ·deque λ± μ΄λ€ μνμ€μλ μΈ μ μμ΅λλ€.
std::binary_searchλ μ΄μ§ νμμ
λλ€. O(log n)μΌλ‘ λΉ λ₯Έ λμ μ¬μ μ λ ¬μ΄ νμ μ μ μ
λλ€. λ λΉκ΅ λ°©μμ΄ ==μ΄ μλλΌ < μ°μ°μ λ λ²μΌλ‘ λμΉλ₯Ό νλ¨ν©λλ€ β !(a < b) && !(b < a)μ΄λ©΄ κ°λ€κ³ λ΄
λλ€. κ²°μ μ μΈ μ°¨μ΄λ λ°ν νμ
μ΄ bool νλλΏμ΄λΌλ μ μ
λλ€. βμλ/μλβλ§ μλ €μ£Όκ³ μμΉλ μ μλ €μ€λλ€. κ·Έλμ μμΉκΉμ§ νμνλ©΄ λ³΄ν΅ std::lower_boundλ std::equal_rangeλ₯Ό μλλ€. μ¬μ€ binary_search λ΄λΆ ꡬν μμ²΄κ° lower_bound νΈμΆμ΄κ³ , μ λ ¬λμ§ μμ 컨ν
μ΄λμ μ¬μ©νλ©΄ κ²°κ³Όλ λ―Έμ μ λμ(UB)μ
λλ€.
μ ν κΈ°μ€μ λ¨μν©λλ€. μ λ ¬λΌ μκ³ μμΉκ° νμ μμΌλ©΄ binary_search, μμΉ iteratorκ° νμνλ©΄ lower_bound, μ λ ¬λΌ μμ§ μκ±°λ μΌνμ±μ΄λ©΄ find. κ·Έλ¦¬κ³ μλ£κ΅¬μ‘° μμ²΄κ° νΈλ¦¬/ν΄μμΈ std::setΒ·std::mapΒ·std::unordered_mapμμλ μκ³ λ¦¬μ¦ ν¨μ λμ λ©€λ² ν¨μ find()λ₯Ό μ¨μΌ ν©λλ€ β μκ³ λ¦¬μ¦ ν¨μλ 컨ν
μ΄λ λ΄λΆ ꡬ쑰λ₯Ό 무μνκ³ O(n)μΌλ‘ λλ λ°λ©΄, λ©€λ² ν¨μλ νΈλ¦¬λ O(log n), ν΄μλ νκ· O(1)μ 보μ₯νκΈ° λλ¬Έμ
λλ€.
ν΅μ¬ κ°λ
| λΆλ₯ | ν€μλ | ν μ€ μ μ |
|---|---|---|
| μ μ | std::find | μ ν νμ. [first, last) μν, ==λ‘ λΉκ΅, iterator λ°ν |
| Β | std::binary_search | μ΄λΆ νμ. μ λ ¬ νμ, <λ‘ λΉκ΅, bool λ°ν |
| ν€λ | <algorithm> | λ ν¨μ λͺ¨λ κ°μ ν€λμ μ μ |
| μκ°λ³΅μ‘λ | O(n) μ ν | find β μ΅μ
nλ² λΉκ΅ |
| Β | O(log n) μ΄λΆ | binary_search β μ΅μ
logβ(n)+1 λ² λΉκ΅ |
| λ°ν νμ | iterator | find β μμΉ μ 보 (λͺ» μ°ΎμΌλ©΄ last) |
| Β | bool | binary_search β μ‘΄μ¬ μ¬λΆλ§ |
| λΉκ΅ μ°μ°μ | == | find β equality λΉκ΅ |
| Β | < λ λ² | binary_search β !(a<b) && !(b<a) λμΉ νλ¨ |
| μ μ | μ λ ¬ λΆνμ | find |
| Β | μ¬μ μ λ ¬ νμ | binary_search β μ λλ©΄ UB |
| Β | Random Access κΆμ₯ | binary_searchλ listμ μ¨λ λμμ νμ§λ§ O(n) 거리 κ³μ°μ΄ λ€μ΄κ° |
| κ΄λ ¨ ν¨μ | std::lower_bound | μ λ ¬ ꡬκ°μμ value μ΄μ 첫 μμΉ iterator λ°ν. binary_search λ΄λΆ ꡬν |
| Β | std::upper_bound | μ λ ¬ ꡬκ°μμ value μ΄κ³Ό 첫 μμΉ iterator λ°ν |
| Β | std::equal_range | {lower_bound, upper_bound} μ λ°ν. λμΌ ν€ λ²μ |
| λ©€λ² vs μκ³ λ¦¬μ¦ | set/map::find | RB-Tree O(log n) λ©€λ² ν¨μ β λ°λμ μ΄κ±Έ μ |
| Β | unordered_map::find | ν΄μ νκ· O(1) λ©€λ² ν¨μ |
| Β | μκ³ λ¦¬μ¦ std::find | 컨ν
μ΄λ ꡬ쑰 무μ O(n) β μ°κ΄ 컨ν
μ΄λμ μ°λ©΄ μν΄ |
| ν¨μ | μ λ ¬ μ λ 컨ν μ΄λ + binary_search | λ―Έμ μ λμ (UB) |
| Β | strict weak ordering κΉ¨μ§ | λΉκ΅μκ° μλͺ»λλ©΄ binary_search κ²°κ³Ό 보μ₯ μ λ¨ |
| μΈλ¦¬μΌ | Algo::Find | std::find λμ (μ ν) |
| Β | Algo::BinarySearch | std::binary_search λμ. int32 μΈλ±μ€ λ°ν (INDEX_NONE = -1) |
| Β | TArray::Find | λ©€λ² ν¨μ. μΈλ±μ€ λ°ν |
λͺ©μ°¨
- ν΅μ¬ μμ½ μΉ΄λ
- std::find β μ ν νμ
- std::binary_search β μ΄λΆ νμ
- ν΅μ¬ μ°¨μ΄μ 5κ°μ§
- κ΄λ ¨ μκ³ λ¦¬μ¦ family β lower_bound / upper_bound / equal_range
- μ½λ λΉκ΅ β vector κΈ°λ°
- 꼬리μ§λ¬Έ μμ κ²½λ‘
- μΈλ¦¬μΌμμμ νμ β Algo::Find / Algo::BinarySearch
- λ³΄κ° β iterator Β· λμΉνλ¨ Β· lower_bound vs find
- λ³΄κ° β ν° λ°μ΄ν°μμ find vs binary_search μ ν
1. ν΅μ¬ μμ½ μΉ΄λ
30μ΄ λ΅λ³
1
2
3
4
5
std::find = μ ν νμ, O(n), iterator λ°ν, μ λ ¬ λΆνμ, == λΉκ΅
std::binary_search = μ΄λΆ νμ, O(log n), bool λ°ν, μ λ ¬ νμ, < λΉκ΅
μμΉκΉμ§ νμνλ©΄ β std::lower_bound (binary_search λ΄λΆ ꡬν)
set/map/unordered_map β λ©€λ² ν¨μ find() μ¬μ© (μκ³ λ¦¬μ¦ X)
꼬리μ§λ¬Έ μ°κ²° λ§΅
1
2
3
4
5
6
7
8
9
std::find vs binary_search
βββ μ binary_searchλ boolλ§? β lower_boundκ° μμΉ λ΄λΉ, λΆμ
μ€κ³
βββ μ λ ¬ μ λλλ° binary_search? β UB (Undefined Behavior)
βββ lower_bound vs upper_bound vs equal_range β μ λ ¬ μκ³ λ¦¬μ¦ family
βββ set/mapμμλ? β λ©€λ² ν¨μ find() (O(log n) / O(1) 보μ₯)
β βββ μ μκ³ λ¦¬μ¦ std::findλ μν΄? β 컨ν
μ΄λ λ΄λΆ ꡬ쑰 무μ β O(n)
βββ < λ λ²μΌλ‘ λμΉ? β strict weak ordering, == μ°μ°μ μμ΄λ λ¨
βββ listμ binary_search? β λμμ ν¨. λ¨ κ±°λ¦¬ κ³μ° O(n) β μλ―Έ μμ
βββ Random Access Iterator vs Forward Iterator
2. std::find β μ ν νμ
ν΅μ¬ ν λ¬Έμ₯
std::findλ[first, last)ꡬκ°μ μ²μλΆν° μννλ©°==μ°μ°μλ‘ κ°μ λΉκ΅ν΄, μΌμΉνλ 첫 μμμ iteratorλ₯Ό λ°ννλ μ ν νμμ λλ€.
μκ·Έλμ²
1
2
3
4
#include <algorithm>
template <class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value);
- ν€λ:
<algorithm> - λ°ν:
valueμ μΌμΉνλ 첫 iterator. λͺ» μ°ΎμΌλ©΄last - μκ°λ³΅μ‘λ: μ΅μ
O(n), μ΅μO(1)(첫 μμκ° μΌμΉ) - μꡬ iterator:
InputIterator(κ°μ₯ μ½ν μꡬμ¬ν βforward_list,istream_iteratorλ±λ κ°λ₯) - λΉκ΅ λ°©μ:
*it == value(equality)
μ¬μ© μμ
1
2
3
4
5
6
7
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
std::cout << "μ°Ύμ! μΈλ±μ€: " << std::distance(v.begin(), it) << "\n";
} else {
std::cout << "μμ\n";
}
λ³ν
std::find_ifβ μ μ΄(predicate) κΈ°λ°.==λμ λλ€λ‘ 쑰건 μ§μ std::find_if_notβ 쑰건μ λ§μ‘±νμ§ μλ 첫 μμ
1
auto it = std::find_if(v.begin(), v.end(), [](int x){ return x > 4; });
3. std::binary_search β μ΄λΆ νμ
ν΅μ¬ ν λ¬Έμ₯
std::binary_searchλ μ λ ¬λ ꡬκ°μμ<μ°μ°μ λ λ²μΌλ‘ λμΉλ₯Ό νλ¨νλ©° μ΄λΆ νμμΌλ‘ κ°μ μ‘΄μ¬ μ¬λΆλ§ νμΈν΄,boolλ§ λ°νν©λλ€.
μκ·Έλμ²
1
2
3
4
5
6
7
8
#include <algorithm>
template <class ForwardIt, class T>
bool binary_search(ForwardIt first, ForwardIt last, const T& value);
// λΉκ΅μ λ²μ
template <class ForwardIt, class T, class Compare>
bool binary_search(ForwardIt first, ForwardIt last, const T& value, Compare comp);
- ν€λ:
<algorithm> - λ°ν:
boolβ μμΌλ©΄true, μμΌλ©΄false. μμΉλ λͺ¨λ¦ - μκ°λ³΅μ‘λ:
O(log n)λΉκ΅ νμ. λ¨RandomAccessIteratorκ° μλλ©΄ 거리 κ³μ°μ΄O(n)μ΄ λ€μ΄κ° - μꡬ iterator:
ForwardIteratorμ΄μ (μ€ν¨λRandomAccessIterator) - λΉκ΅ λ°©μ:
!(a < b) && !(b < a)β<λ λ²μΌλ‘ λμΉ νλ¨
μ¬μ© μμ
1
2
3
4
5
6
7
8
9
std::vector<int> v = {1, 1, 2, 3, 4, 5, 6, 9}; // β
λ°λμ μ λ ¬
bool found = std::binary_search(v.begin(), v.end(), 5);
std::cout << (found ? "μμ" : "μμ") << "\n"; // μμ
// μμΉκΉμ§ μκ³ μΆλ€λ©΄ β lower_bound
auto it = std::lower_bound(v.begin(), v.end(), 5);
if (it != v.end() && *it == 5) {
std::cout << "μμΉ: " << std::distance(v.begin(), it) << "\n";
}
ν¨μ
- μ λ ¬ μ λ 컨ν μ΄λ: κ²°κ³Ό 보μ₯ X β Undefined Behavior
==μ°μ°μλ§ μ μλ νμ : μ»΄νμΌμ λμ§λ§ μλ―Έκ° κΉ¨μ§.<λΉκ΅μκ° strict weak orderingμ λ§μ‘±ν΄μΌ ν¨std::listμ μ¬μ©: λμμ νμ§λ§ 거리 κ³μ°μ΄O(n)β μλ―Έ μμ
4. ν΅μ¬ μ°¨μ΄μ 5κ°μ§
| νλͺ© | std::find | std::binary_search |
|---|---|---|
| μκ³ λ¦¬μ¦ | μ ν νμ | μ΄λΆ νμ |
| μκ°λ³΅μ‘λ | O(n) | O(log n) (λΉκ΅ νμ κΈ°μ€) |
| μ¬μ μ λ ¬ | λΆνμ | νμ (μ λλ©΄ UB) |
| λ°ν νμ | Iterator (μμΉ) | bool (μ‘΄μ¬ μ¬λΆλ§) |
| λΉκ΅ μ°μ°μ | == (equality) | < λ λ² (strict weak ordering) |
| μꡬ iterator | InputIterator | ForwardIterator (μ€ν¨λ RandomAccess) |
| μ μ© μ»¨ν μ΄λ | vector, list, deque, forward_list, λͺ¨λ μνμ€ | μ λ ¬λ vector, deque, array (RandomAccess κΆμ₯) |
| μ¬μ© μμ | μ λ ¬ μ λ¨ / μΌνμ± / μμΉ νμ | μ λ ¬ μλ£ / λ€ν μ‘°ν / μ‘΄μ¬λ§ νμΈ |
| ν¨μ | n ν¬λ©΄ λλ¦Ό | μ λ ¬ μ λλ©΄ UB |
μ μ΄λ° μ°¨μ΄κ° μκ²Όλ
findλ κ°μ₯ μΌλ°μ μΈ νμ β μ΄λ€ iteratorλ λ°κ³ μ΄λ€ 컨ν μ΄λλ λ°κΈ° μν΄ μ νμΌλ‘ μ€κ³λ¨. μμΉ μ λ³΄κ° ν΅μ¬μ΄λΌ iterator λ°ν.binary_searchλ μ λ ¬ μλ£μ νΉνλ λΉ λ₯Έ μ‘°ν β μμΉ μ± μμ λΆλ¦¬ν΄μlower_boundκ° κ°μ Έκ°. κ·Έλμbinary_searchλ λ¨μνboolλ§ λ°ν.- μ΄κ² STLμ λΆμ
μ€κ³ μ² ν: μ‘΄μ¬ νμΈμ
binary_search, μμΉ νμΈμlower_bound, λ²μ νμΈμequal_range.
5. κ΄λ ¨ μκ³ λ¦¬μ¦ family β lower_bound / upper_bound / equal_range
ν΅μ¬ ν λ¬Έμ₯
binary_searchλ΄λΆλlower_boundνΈμΆμ΄κ³ , μμΉΒ·λ²μκ° νμνλ©΄lower_boundΒ·upper_boundΒ·equal_rangeμ μ΄ μ λ ¬ μλ£ νμμ μ§μ§ λꡬμ λλ€.
μκ·Έλμ²
1
2
3
4
5
6
7
8
9
10
11
template <class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);
// value μ΄μμΈ μ²« μμΉ
template <class ForwardIt, class T>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value);
// value μ΄κ³ΌμΈ 첫 μμΉ
template <class ForwardIt, class T>
std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value);
// {lower_bound, upper_bound} μ β valueμ κ°μ μμλ€μ λ²μ
binary_search λ΄λΆ ꡬν (κ°λ )
1
2
3
4
5
template <class It, class T>
bool binary_search(It first, It last, const T& value) {
auto it = std::lower_bound(first, last, value);
return it != last && !(value < *it); // <λ§ μ¬μ© (==μ μ μ)
}
β binary_searchλ lower_bound + λμΉ κ²μ¬ ν μ€μ§λ¦¬ wrapperμ
λλ€. β μ΄κ±Έ μλ©΄ βμ binary_searchλ iterator μ λλ €μ€?βμ λ΅μ΄ λͺ
νν΄μ§λλ€ β lower_boundκ° μ΄λ―Έ κ·Έ μν .
λΉκ΅ ν
| ν¨μ | λ°ν | μ©λ | λΉκ³ |
|---|---|---|---|
binary_search | bool | μ‘΄μ¬ μ¬λΆλ§ | λ΄λΆλ lower_bound |
lower_bound | iterator | value μ΄μ 첫 μμΉ | μ½μ μμΉ κ²°μ μλ μ¬μ© |
upper_bound | iterator | value μ΄κ³Ό 첫 μμΉ | lower_boundμ μ |
equal_range | pair<It, It> | κ°μ κ°λ€μ λ²μ | multiset/multimapμμ μμ£Ό |
μ λ ¬ 컨ν μ΄λμμ multi ν€ λ€λ£° λ
1
2
3
std::vector<int> v = {1, 2, 2, 2, 3, 4}; // μ λ ¬ + μ€λ³΅
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 2);
std::cout << "2μ κ°μ: " << std::distance(lo, hi) << "\n"; // 3
6. μ½λ λΉκ΅ β vector κΈ°λ°
find μ¬μ©
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6}; // μ λ ¬ X
// μ ν νμ β μ΄λ€ μμλ OK
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
std::cout << "find: μμΉ " << std::distance(v.begin(), it)
<< ", κ° " << *it << "\n";
}
// μΆλ ₯: find: μμΉ 4, κ° 5
}
binary_search μ¬μ©
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
std::sort(v.begin(), v.end()); // β
μ¬μ μ λ ¬ νμ
// v = {1, 1, 2, 3, 4, 5, 6, 9}
bool found = std::binary_search(v.begin(), v.end(), 5);
std::cout << "binary_search: " << (found ? "μμ" : "μμ") << "\n";
// μΆλ ₯: binary_search: μμ
// μμΉκΉμ§ νμνλ©΄ lower_bound
auto it = std::lower_bound(v.begin(), v.end(), 5);
if (it != v.end() && *it == 5) {
std::cout << "lower_bound: μμΉ " << std::distance(v.begin(), it) << "\n";
}
// μΆλ ₯: lower_bound: μμΉ 5
}
μ±λ₯ μ°¨μ΄ μ²΄κ° (n = 1,000,000)
1
2
μ λ ¬ μ ν¨ + std::find β νκ· ~500,000 λΉκ΅ (O(n))
μ λ ¬ 1ν (O(n log n)) + std::binary_search 100λ§ λ² β μ½ 20 λΉκ΅ Γ 100λ§
β λ€ν μ‘°νλ©΄ μ λ ¬ + binary_searchκ° μλμ , μΌνμ±μ΄λ©΄ findκ° λ¨μνκ³ λΉ λ¦.
7. 꼬리μ§λ¬Έ μμ κ²½λ‘
Q1. βμ binary_searchλ iteratorλ₯Ό μ λλ €μ£Όλμ?β
STLμ μ± μμ λΆλ¦¬ν΄μ μ€κ³νμ΅λλ€. μ‘΄μ¬ μ¬λΆλ§ νμΈνλ λΉ λ₯Έ κ²½λ‘λ
binary_search(bool), μμΉκΉμ§ μκ³ μΆμΌλ©΄lower_bound(iterator), κ°μ κ°λ€μ λ²μλequal_range(pair). μ¬μ€binary_searchλ΄λΆ ꡬν μ체κ°lower_boundλ₯Ό νΈμΆν λ€!(value < *it)ν μ€λ‘ λμΉ κ²μ¬λ§ νλ wrapperμ λλ€. μμΉκ° νμνλ©΄lower_boundλ₯Ό μ§μ λΆλ₯΄λ κ² λ ν¨μ¨μ μ΄μμ.
Q2. βμ λ ¬ μ λ 컨ν μ΄λμ binary_search μ°λ©΄ μ΄λ»κ² λλμ?β
Undefined Behaviorμ λλ€. νμ€μ βμ λ ¬λΌ μλ€βλ₯Ό μ μ λ‘λ§ λμμ 보μ₯ν©λλ€. μ΄μ΄ μ’μΌλ©΄ μ°μ°ν λ§μ μλ μμ§λ§ μΌλ°μ μΌλ‘λ μλͺ»λ κ²°κ³Ό λλ 무ν λΆν λ‘ λλμ§ μμ μλ μμ΅λλ€. κ·Έλμ
binary_searchνΈμΆ μ μ λ°λμstd::is_sortedλ‘ κ²μ¦νκ±°λstd::sortλ‘ μ λ ¬ν΄μΌ ν©λλ€.
Q3. βsetμ΄λ mapμμλ λ©€λ² ν¨μ findμ μκ³ λ¦¬μ¦ std::find μ€ λ μ¨μΌ νλμ?β
λ°λμ λ©€λ² ν¨μ
find()μ λλ€.std::set::findλ RB-Treeλ₯Ό νκ³O(log n),std::unordered_map::findλ ν΄μ λ²ν· ν λ² μ‘°νλ‘ νκ·O(1)μ 보μ₯ν©λλ€. λ°λ©΄ μκ³ λ¦¬μ¦std::findλ 컨ν μ΄λ λ΄λΆ ꡬ쑰λ₯Ό λͺ¨λ₯΄κ³ κ·Έλ₯ iteratorλ₯Ό μ²μλΆν° λκΉμ§ λλO(n)μ ν νμμ λλ€. μλ£κ΅¬μ‘°μ μ₯μ μ ν΅μ§Έλ‘ λ²λ¦¬λ μ μ΄λΌ μ λ μ μλλ€. νμ€ λΌμ΄λΈλ¬λ¦¬μμ λ©€λ² ν¨μκ° λ°λ‘ μλ€λ©΄ κ±°μ νμ κ·Έκ² λ λΉ λ¦ λλ€.
Q4. βbinary_searchμ λΉκ΅κ° < λ λ²μΈ μ΄μ λ?β
strict weak ordering λ§ μꡬνλ STLμ μΌκ΄λ μ€κ³ λλ¬Έμ λλ€.
==μ°μ°μκ° μ μλμ§ μμ νμ (μ: μ¬μ©μ μ μ ν΄λμ€)λ<λ§ μ μλΌ μμΌλ©΄binary_searchλ₯Ό μΈ μ μμ΅λλ€.!(a < b) && !(b < a)κ° μ°Έμ΄λ©΄ λ κ°μ βλλ±βνλ€κ³ κ°μ£Όν©λλ€. μ΄κ±΄std::setμ΄λstd::mapμ΄<λΉκ΅μλ§μΌλ‘ λμνλ κ²κ³Ό κ°μ μ리μ λλ€.
Q5. βlistμ binary_search μ°λ©΄ λμνλμ?β
λμμ ν©λλ€.
binary_searchλForwardIteratorλ§ μꡬνλκΉμ. νμ§λ§std::listλRandomAccessIteratorκ° μλλΌ μ€κ° μμΉλ‘ μ ννλ λ°O(n)거리 κ³μ°μ΄ λ€μ΄κ°λλ€. κ²°κ΅ λΉκ΅ νμλ§O(log n)μ΄μ§ μ 체λO(n)μ΄ λΌμ μλ―Έκ° μμ΅λλ€. μ΄λΆ νμμ μ΄λμ λ³΄λ €λ©΄vector,deque,arrayμ²λΌ random accessκ° κ°λ₯ν 컨ν μ΄λλ₯Ό μ¨μΌ ν©λλ€.
Q6. βfindμ binary_search μΈμ λ€λ₯Έ νμ μκ³ λ¦¬μ¦μ?β
std::find_if(μ μ΄ κΈ°λ° μ ν),std::find_first_of(μ¬λ¬ ν보 μ€ μ²« μΌμΉ),std::adjacent_find(μΈμ λμΌ μμ),std::search(λΆλΆ μνμ€ λ§€μΉ),std::count/std::count_if(κ°μ μΈκΈ°),std::any_of/std::all_of/std::none_of(쑰건 μΆ©μ‘± μ¬λΆ) λ±μ΄ μμ΅λλ€. μ λ ¬ μλ£ μ μ©μΌλ‘λ μμ λ§νlower_boundΒ·upper_boundΒ·equal_rangeκ° ν΅μ¬ familyμ λλ€.
Q7. βbinary_search κ²°κ³Όλ₯Ό λ°μμ μμΉλ₯Ό λ lower_boundλ‘ μ°ΎμΌλ©΄ λΉν¨μ¨ μλκ°μ?β
μ νν©λλ€. κ·Έλμ μμΉκ° νμνλ©΄ μ²μλΆν°
lower_boundλ§ λΆλ₯΄λ κ² μ μμ λλ€. ν¨ν΄μ μ΄λ κ² λ©λλ€:
1 2 3 4 auto it = std::lower_bound(v.begin(), v.end(), value); if (it != v.end() && *it == value) { // μ°Ύμ + μμΉλ it }
binary_searchλ μ λ§ βμλ μλβλ§ νμν λ, λλ μλλ₯Ό λͺ νν νννκ³ μΆμ λλ§ μλλ€.
8. μΈλ¦¬μΌμμμ νμ β Algo::Find / Algo::BinarySearch
ν΅μ¬ ν λ¬Έμ₯
μΈλ¦¬μΌμ
Algo::λ€μμ€νμ΄μ€μstd::μκ³ λ¦¬μ¦ λμ ν¨μλ₯Ό λκ³ , 컨ν μ΄λ μ체μλFindκ°μ λ©€λ² ν¨μλ₯Ό μ κ³΅ν΄ μΈλ±μ€ λλ ν¬μΈν° κΈ°λ°μΌλ‘ λμν©λλ€.
λμ ν
| std:: | Unreal Algo:: / λ©€λ² ν¨μ | λ°ν |
|---|---|---|
std::find | Algo::Find(Arr, Value) | T* (λͺ» μ°ΎμΌλ©΄ nullptr) |
std::find_if | Algo::FindByPredicate | T* |
std::binary_search | Algo::BinarySearch(Arr, Value) | int32 μΈλ±μ€ (λͺ» μ°ΎμΌλ©΄ INDEX_NONE = -1) |
std::lower_bound | Algo::LowerBound | int32 |
std::upper_bound | Algo::UpperBound | int32 |
std::sort | Algo::Sort | void |
TArray::Find | (λ©€λ² ν¨μ) | int32 μΈλ±μ€ |
TArray::Contains | (λ©€λ² ν¨μ) | bool |
μ½λ μμ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "Algo/Find.h"
#include "Algo/BinarySearch.h"
TArray<int32> Arr = {3, 1, 4, 1, 5, 9, 2, 6};
// μ ν νμ β μΈλ±μ€
int32 Idx = Arr.Find(5); // TArray λ©€λ² ν¨μ
if (Idx != INDEX_NONE) { /* ... */ }
// μ ν νμ β ν¬μΈν°
int32* Ptr = Algo::Find(Arr, 5);
if (Ptr) { /* *Ptr μ¬μ© κ°λ₯ */ }
// μ΄λΆ νμ (μ λ ¬ νμ)
Arr.Sort(); // 1, 1, 2, 3, 4, 5, 6, 9
int32 BIdx = Algo::BinarySearch(Arr, 5);
if (BIdx != INDEX_NONE) { /* ... */ }
μ°¨μ΄μ
- μΈλ¦¬μΌμ
int32μΈλ±μ€ λ°νμ μ νΈ βINDEX_NONE(-1) λ§€ν¬λ‘λ‘ not-found νν Algo::Findλ ν¬μΈν° λ°ν βnullptrκ²μ¬λ‘ not-found μ²λ¦¬TArray::Find/TArray::Containsβ λ©€λ² ν¨μκ° κ°μ₯ μΌλ°μ . μκ³ λ¦¬μ¦ ν¨μλ³΄λ€ μ½λκ° κ°κ²°- μΈλ¦¬μΌμ
<algorithm>μ§μ μ¬μ©λ κ°λ₯νμ§λ§Algo::familyμ λ©€λ² ν¨μκ° μ»¨λ²€μ
9. λ³΄κ° β iterator Β· λμΉνλ¨ Β· lower_bound vs find
λ³Έλ¬Έμ μ½κ³ μΆκ°λ‘ μκΈ΄ μλ¬Έ(2026-05-06)μ ν μΉμ μΌλ‘ λ¬Άμ. β iteratorκ° λκ° β‘ findλ μΈλ±μ€λ₯Ό λλ €μ£Όλκ° μ΄ν°λ μ΄ν°λ₯Ό λλ €μ£Όλκ° β’ λμΉνλ¨μ΄λ β£ lower_boundμ findμ κ²°μ μ μ°¨μ΄.
9-1. iteratorλ
컨ν μ΄λ μμλ₯Ό κ°λ¦¬ν€λ βν¬μΈν° κ°μ κ°μ²΄β. ν¬μΈν°μ²λΌ μμ°Έμ‘°Β·μ¦κ°Β·λΉκ΅κ° κ°λ₯νμ§λ§,
vectorΒ·listΒ·mapλ± λ΄λΆ κ΅¬μ‘°κ° λ€λ₯Έ 컨ν μ΄λλ₯Ό κ°μ μΈν°νμ΄μ€λ‘ λ€λ£¨κΈ° μν μΆμνμ λλ€.
ν΅μ¬ μ°μ° μΈ κ°μ§:
| μ°μ° | μλ―Έ |
|---|---|
*it | μμ°Έμ‘° β κ°λ¦¬ν€λ μμμ κ° |
++it | λ€μ μμλ‘ μ΄λ |
it == end | λμΈμ§ λΉκ΅ (==/!=) |
1
2
3
4
5
6
std::vector<int> v = {3, 1, 4};
auto it = v.begin(); // 첫 μμλ₯Ό κ°λ¦¬ν΄
*it; // 3
++it; // λ λ²μ§Έλ‘ μ΄λ
*it; // 1
v.end(); // β
λ§μ§λ§μ "λ€μ" μ리 β μ ν¨ μμ X (past-the-end)
end()λ μ ν¨ μμκ° μλλ€ β λ§μ§λ§ μμ λ€μμ κ°μ μμΉ(past-the-end). κ·Έλμ STLμ λͺ¨λ μκ³ λ¦¬μ¦μ [first, last) λ°μ΄λ¦° ꡬκ°μΌλ‘ λμν©λλ€. findκ° λͺ» μ°ΎμΌλ©΄ lastλ₯Ό λ°ννλ€λ λ§μ βμ ν¨νμ§ μμ λ μ리βλ₯Ό κ°λ¦¬ν¨λ€λ λ»μ΄λΌ μμ ν©λλ€.
iterator μΉ΄ν κ³ λ¦¬ (κ°ν¨ μ)
| μΉ΄ν κ³ λ¦¬ | κ°λ₯ μ°μ° | λν 컨ν μ΄λ |
|---|---|---|
| Input | ++it, *it(μ½κΈ° μ μ©, 1ν) | istream_iterator |
| Forward | + *itλ‘ μ¬λ¬ λ² μ½κΈ° | forward_list |
| Bidirectional | + --it μλ°©ν₯ | list, set, map |
| Random Access | + it + n, it[n], it < it2 | vector, deque, array |
β binary_searchκ° vectorμμ μ§μ§ O(log n)μΈ μ΄μ = Random Accessμ¬μ μ€κ° μ νκ° O(1). β listμ binary_searchλ₯Ό μ¨λ λμνμ§λ§ μ νκ° O(n)μ΄λΌ μλ―Έ μλ μ΄μ λ κ°μ.
9-2. findλ μΈλ±μ€? iterator?
std::findλ iteratorλ₯Ό λ°νν©λλ€. μΈλ±μ€ μλλλ€. λͺ» μ°ΎμΌλ©΄ μΈλ±μ€ -1μ΄ μλλΌlast(=v.end()) λ₯Ό λλ €μ€λλ€.
1
2
3
4
5
6
auto it = std::find(v.begin(), v.end(), 999);
if (it == v.end()) { /* λͺ» μ°Ύμ */ } // β μ μ ν¨ν΄
if (it != v.end()) { /* μ°Ύμ β *it μ¬μ© κ°λ₯ */ }
// μΈλ±μ€κ° νμνλ©΄ λ³ν
int idx = std::distance(v.begin(), it);
μΈμ΄Β·λΌμ΄λΈλ¬λ¦¬λ³ not-found νν μ°¨μ΄ β ν·κ°λ¦¬λ μ§μ
| API | λ°ν νμ | λͺ» μ°Ύμμ λ |
|---|---|---|
std::find (C++ STL) | iterator | last (= end()) |
std::string::find | size_t | std::string::npos (= -1μ unsignedλ‘) |
TArray::Find (Unreal) | int32 μΈλ±μ€ | INDEX_NONE (= -1) |
Algo::Find (Unreal) | T* ν¬μΈν° | nullptr |
std::map::find (λ©€λ²) | iterator | end() |
β βfindλ λͺ» μ°ΎμΌλ©΄ -1β μ std::stringμ΄λ μΈλ¦¬μΌ 컨벀μ
μ΄μ§, <algorithm>μ std::findκ° μλ. β λͺ¨λ STL μκ³ λ¦¬μ¦μ not-found = last λ‘ ν΅μΌ.
9-3. λμΉνλ¨(equivalence) β ==μ΄ μλλΌ < λ λ²
binary_searchλ==λ‘ κ°μμ§ λ³΄μ§ μκ³<λ₯Ό λ λ² νΈμΆν΄ βμ΄λ μͺ½λ λ μμ§ μλ€β λ‘ κ°μμ§ νλ¨ν©λλ€. μ΄κ±Έ λμΉ(equivalence) λΌκ³ λΆλ₯΄λ©°, μΌλ° λλ±μ±(equality)κ³Ό ꡬλΆλ©λλ€.
1
2
3
4
5
// equality (findμ λ°©μ)
a == b
// equivalence (binary_search Β· set Β· mapμ λ°©μ)
!(a < b) && !(b < a)
μ κ΅³μ΄ μ΄λ κ²?
<λ§ μ μλΌ μμ΄λ λμνλλ‘ λ§λ STLμ μΌκ΄λ μ€κ³- μ¬μ©μ μ μ ν΄λμ€μμ
==μ μ λ§λ€κ³<λ§ λ§λ€μ΄λbinary_searchΒ·setΒ·mapμ΄ λͺ¨λ μλ - μ΄κ±Έ strict weak orderingμ΄λΌκ³ λΆλ¦ β
<λΉκ΅μκ° λ§μ‘±ν΄μΌ νλ μνμ 쑰건
1
2
3
4
5
6
7
8
9
10
struct Point {
int x, y;
bool operator<(const Point& o) const { return x < o.x; }
// operator== μμ΄λ OK
};
std::vector<Point> pts = { {1,0}, {3,0}, {5,0} };
std::binary_search(pts.begin(), pts.end(), Point{3, 99});
// β xμ’νλ§ λΉκ΅ β !(3<3) && !(3<3) = true β λμΉλ‘ νλ¨ β true
// yκ° λ¬λΌλ "λμΉ"λ‘ λ΄ β μ΄κ² equivalenceμ equalityμ ν΅μ¬ μ°¨μ΄
β ==λ κ°μ²΄ μμ²΄κ° κ°μ (entity equality) β λμΉλ μμ κΈ°μ€μμ κ°μ μμΉ (μ΄λ μͺ½λ λ μμ§ μμ) β λμ΄ λ€λ₯Ό μ μλ€λ μ μ΄ ν¨μ β setμμ κ°μ ν€λ‘ μ·¨κΈλλ λ κ°μ΄ ==λ‘λ λ€λ₯Ό μ μμ.
9-4. lower_bound vs find β κ²°μ μ μ°¨μ΄
λ λ€ βμμΉ iteratorλ₯Ό λλ €μ€λ€βλ μ μ κ°μ§λ§, μ μ Β·μκ°λ³΅μ‘λΒ·λ°ν μλ―ΈΒ·λΆκ° λ₯λ ₯μ΄ λ€λ¦ λλ€. κ°μ₯ ν° ν¨μ μ lower_boundλ λͺ» μ°Ύμλ
lastκ° μλ μμΉλ₯Ό κ°λ¦¬ν¬ μ μλ€λ μ .
λΉκ΅ν
| νλͺ© | std::find | std::lower_bound |
|---|---|---|
| μκ³ λ¦¬μ¦ | μ ν | μ΄λΆ |
| μ λ ¬ μ μ | λΆνμ | νμ |
| μκ°λ³΅μ‘λ | O(n) | O(log n) |
| λΉκ΅ μ°μ°μ | == | < |
| λ°ν | μΌμΉνλ 첫 iterator | value μ΄μμΈ μ²« iterator |
| λͺ» μ°Ύμ λ λ°ν | last (λͺ
ν) | last λλ valueλ³΄λ€ ν° λ€λ₯Έ μμΉ (μΆκ° κ²μ¬ νμ) |
| λΆκ° μ©λ | μμΉ μ°ΎκΈ°λ§ | μ λ ¬ μ μ§ μ½μ μμΉ κ³μ° |
| iterator μꡬ | InputIterator | ForwardIterator (μ€ν¨ RandomAccess) |
ν¨μ β lower_boundλ λ λ¨κ³ κ²μ¬κ° νμ
1
2
3
4
5
6
7
8
9
10
std::vector<int> v = {1, 3, 5, 7}; // μ λ ¬λ¨, 4λ μμ
// (A) find β ν λ²λ§ κ²μ¬νλ©΄ λ¨
auto it1 = std::find(v.begin(), v.end(), 4);
if (it1 != v.end()) { /* μ°Ύμ */ } // it1 == end() λΌμ μ§μ
μ ν¨ β λͺ
ν
// (B) lower_bound β itλ 5λ₯Ό κ°λ¦¬ν΄ (4 μ΄μ 첫 μμΉ)
auto it2 = std::lower_bound(v.begin(), v.end(), 4);
// it2 != v.end() λ§ κ²μ¬νλ©΄ μ λ¨!
if (it2 != v.end() && *it2 == 4) { /* μ°Ύμ */ } // β λ λ¨κ³ κ²μ¬ νμ
β findμ lastλ βμλ€β β lower_boundμ lastλ βvalueλ³΄λ€ ν¬κ±°λ κ°μ κ² νλλ μλ€β (μ¦ λͺ¨λ μμκ° value λ―Έλ§) β lower_boundκ° lastκ° μλ μμΉλ₯Ό κ°λ¦¬μΌλ κ·Έκ² valueμΈμ§ μλμ§λ λ³λ κ²μ¬ νμ.
lower_boundλ§μ λ₯λ ₯ β μ λ ¬ μ μ§ μ½μ
1
2
3
4
std::vector<int> v = {1, 3, 5, 7};
auto pos = std::lower_bound(v.begin(), v.end(), 4);
v.insert(pos, 4);
// v = {1, 3, 4, 5, 7} β μ λ ¬ μ μ§
β findλ‘λ λΆκ°λ₯. lower_boundλ βνμ + μ½μ
μμΉ κ²°μ β λ μν μ κ²Έν©λλ€. β κ·Έλμ μ λ ¬λ μλ£μμ βμ΄ κ°μ΄ μλμ§ + μμΌλ©΄ μ΄λ λΌμΈμ§βλ₯Ό ν λ²μ μ²λ¦¬ν λ lower_boundλ§ λΆλ₯΄λ©΄ λ¨.
9-5. equal_range β μ¬μ©λ²κ³Ό λ°νκ° λΆν΄
std::equal_rangeλ μ λ ¬ ꡬκ°μμvalueμ λμΉμΈ μμλ€μ λ²μλ₯Όpair<iterator, iterator>λ‘ λ°νν©λλ€. μ¦{lower_bound, upper_bound}ν μμ ν λ²μ λλ €μ€λλ€. μ€λ³΅μ΄ μλ μ λ ¬ μλ£μμ βκ°μ κ°μ΄ μ΄λλΆν° μ΄λκΉμ§λβλ₯Ό ꡬν λ ν΅μ¬.
μκ·Έλμ²
1
2
3
4
5
6
7
8
template <class ForwardIt, class T>
std::pair<ForwardIt, ForwardIt>
equal_range(ForwardIt first, ForwardIt last, const T& value);
// λΉκ΅μ λ²μ
template <class ForwardIt, class T, class Compare>
std::pair<ForwardIt, ForwardIt>
equal_range(ForwardIt first, ForwardIt last, const T& value, Compare comp);
- ν€λ:
<algorithm> - λ°ν:
pair<It, It>β.first= lower_bound,.second= upper_bound - μκ°λ³΅μ‘λ:
O(log n)λΉκ΅ (RandomAccess κΈ°μ€) - μ μ : μ λ ¬λΌ μμ΄μΌ ν¨ (μ λλ©΄ UB)
λ°νκ°μ μλ―Έ μκ°ν
1
2
3
4
5
6
7
8
9
v = {1, 2, 2, 2, 3, 4} (μΈλ±μ€ 0 1 2 3 4 5)
^
equal_range(v.begin(), v.end(), 2)
βββββ .first (lower_bound) β μΈλ±μ€ 1, *it == 2 (첫 2)
β βββ .second (upper_bound) β μΈλ±μ€ 4, *it == 3 (2 λ€μ 첫 μμΉ)
βΌ βΌ
[1] [2] [2] [2] [3] [4]
ββββ λμΉ λ²μ [first, second) = μΈλ±μ€ 1~3 ββββ
β .first = value μ΄μ 첫 μμΉ (= 첫 λ±μ₯ μμΉ) β .second = value μ΄κ³Ό 첫 μμΉ (= λ§μ§λ§ λ±μ₯ + 1, λ°μ΄λ¦° λ) β [.first, .second) λ°μ΄λ¦° ꡬκ°μ΄ valueμ λμΉμΈ μμ μ 체
μ¬μ© ν¨ν΄ β 4κ°μ§
β κ°μ μΈκΈ°
1
2
3
std::vector<int> v = {1, 2, 2, 2, 3, 4};
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 2); // C++17 ꡬ쑰μ λ°μΈλ©
std::cout << std::distance(lo, hi) << "\n"; // 3
β‘ μ‘΄μ¬ μ¬λΆ νμΈ
1
2
3
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 2);
if (lo != hi) { /* μμ */ } // 거리 > 0
else { /* μμ */ } // 거리 == 0 β λ iteratorκ° κ°μ μμΉ
β λͺ» μ°Ύμμ λλ .first == .second κ° λλ©° κ°μ μμΉλ₯Ό κ°λ¦¬ν΄ β κ·Έ μλ¦¬κ° μ½μ
μμΉ.
β’ λμΉ μμ μ 체 μν
1
2
3
4
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 2);
for (auto it = lo; it != hi; ++it) {
std::cout << *it << " "; // 2 2 2
}
⣠ꡬ쑰μ λ°μΈλ© μμ΄ (C++14 μ΄ν)
1
2
3
4
auto p = std::equal_range(v.begin(), v.end(), 2);
auto lo = p.first;
auto hi = p.second;
int cnt = static_cast<int>(std::distance(lo, hi));
multiset / multimapμμμ νμ©
equal_rangeκ° μ§μ§ λΉμ 보λ κ³³μ μ€λ³΅ ν€λ₯Ό νμ©νλ μ°κ΄ 컨ν μ΄λμ λλ€. κ°μ ν€μ λͺ¨λ κ°μ ν λ²μ μ‘μλΌ λ.
1
2
3
4
5
6
7
8
9
std::multimap<std::string, int> scores = {
{"Alice", 90}, {"Alice", 85}, {"Bob", 70}, {"Alice", 95}
};
auto [lo, hi] = scores.equal_range("Alice"); // λ©€λ² ν¨μ β O(log n)
for (auto it = lo; it != hi; ++it) {
std::cout << it->first << ": " << it->second << "\n";
// Alice: 90 / Alice: 85 / Alice: 95
}
β multimap/multisetμμ κ°μ ν€ λͺ¨λ κ°μ Έμ€λ μ μΌν μ μ λ°©λ² (λ°λ³΅ findλ‘λ 첫 κ°λ§). β λ©€λ² ν¨μ equal_rangeκ° λ°λ‘ μλ€ β μκ³ λ¦¬μ¦ std::equal_rangeλ³΄λ€ μλ£κ΅¬μ‘° μΉνμ .
λͺ» μ°Ύμμ λ β .first == .second μ μλ―Έ
1
2
3
4
5
std::vector<int> v = {1, 3, 5, 7};
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 4);
// lo == hi (λ λ€ 5 μμΉ, μΈλ±μ€ 2λ₯Ό κ°λ¦¬ν΄)
// distance(lo, hi) == 0 β 4λ μμ
// κ·Έ μλ¦¬κ° μ λ ¬ μ μ§ μ½μ
μμΉ
β βμ°Ύμ§ λͺ»ν μμΉ = μ λ ¬ μ μ§ μ½μ μμΉβλΌλ lower_boundμ μ±μ§μ΄ κ·Έλλ‘ μ μ§λ¨.
lower_bound + upper_bound λ°λ‘ νΈμΆ vs equal_range
1
2
3
4
5
6
// (A) λ°λ‘ νΈμΆ β νΈλ¦¬/μ΄λΆ νμ 2λ²
auto lo = std::lower_bound(v.begin(), v.end(), 2);
auto hi = std::upper_bound(v.begin(), v.end(), 2);
// (B) equal_range β ν λ²μ
auto [lo, hi] = std::equal_range(v.begin(), v.end(), 2);
β νμ€μ (B)λ₯Ό λ¨μΌ ν¨μ€λ‘ μ΅μ ν κ°λ₯νκ² λͺ
μΈ β μΌλΆ ꡬνμ λΆκΈ° μ μ½. μλ ννλ λͺ
ν. β βλ²μκ° νμνλ€βκ° μλλ©΄ equal_range μ§μ ν.
λ°νκ° μ 리 μΉ΄λ
1
2
3
4
5
6
7
equal_range(λ²μ, value) β pair<It, It>
ββ .first = lower_bound β value μ΄μ 첫 μμΉ
ββ .second = upper_bound β value μ΄κ³Ό 첫 μμΉ
ββ [first, second) β valueμ λμΉμΈ μμ μ 체
ββ distance(first, second) β valueμ κ°μ
ββ first == second β μμ + κ·Έ μλ¦¬κ° μ½μ
μμΉ
ββ multi컨ν
μ΄λμμ ν΅μ¬ β κ°μ ν€ μ 체 κ°μ Έμ€κΈ°
μΈλ¦¬μΌ λμ
μΈλ¦¬μΌμ Algo:: λ€μμ€νμ΄μ€μ EqualRangeκ° μκ±°λ λ§€μ° μ νμ μ΄λΌ λ³΄ν΅ μ§μ μ‘°ν©:
1
2
3
4
5
6
7
8
TArray<int32> Arr = {1, 2, 2, 2, 3, 4};
int32 Lo = Algo::LowerBound(Arr, 2); // 1
int32 Hi = Algo::UpperBound(Arr, 2); // 4
int32 Count = Hi - Lo; // 3
// TMultiMapμ λμΉ ν€ λͺ¨λ κ°μ Έμ€κΈ°
TArray<FValue> Values;
MultiMap.MultiFind(Key, Values); // λ©€λ² ν¨μ β equal_range λμ
β μΈλ¦¬μΌμμλ MultiFind / LowerBound+UpperBound μ‘°ν©μ΄ 컨벀μ
.
10. λ³΄κ° β ν° λ°μ΄ν°μμ find vs binary_search μ ν
βν° λ°μ΄ν°λ©΄ 무쑰건 binary_searchκ° λ«μ§ μλ?βλ μ λ°λ§ λ§λ λ΅μ λλ€. μ λ ¬ λΉμ©Β·μ‘°ν νμΒ·μΊμ μΉνμ±μ΄ μμ΅μ κ°λ¦ λλ€. λ°μ΄ν°κ° ν΄μλ‘ μ€νλ € λ€μ― κ°μ§ λ³μλ₯Ό λ°μ ΈμΌ ν©λλ€.
10-1. κ²°λ‘ λΆν° β 5κ°μ§ μλ리μ€
| μν© | μ λ΅ | μ΄μ |
|---|---|---|
| μ΄λ―Έ μ λ ¬λΌ μμ + λ¨λ° μ‘°ν | binary_search / lower_bound | μ λ ¬ λΉμ© 0, O(log n) κ·Έλλ‘ μ΄λ |
| μ λ ¬ μ λ¨ + 1ν μ‘°ν | find | μ λ ¬ λΉμ© O(n log n) > νμ λΉμ© O(n). μ λ ¬μ μν΄ |
| μ λ ¬ μ λ¨ + kν λ°λ³΅ μ‘°ν | kκ° ν¬λ©΄ μ λ ¬+binary_search | μμ΅λΆκΈ°μ μ k β³ log n λΆκ·Ό |
| nμ΄ λ§€μ° νΌ + λμμ±Β·μ½μ μ¦μ | unordered_set/map (ν΄μ) | νκ· O(1). λΉλ λμ μ‘°νλ©΄ μλ£κ΅¬μ‘° μ체λ₯Ό λ°κΏ |
| nμ΄ μμ (~μμ~μλ°±) | find | μΊμΒ·λΆκΈ° μμΈ‘ ν¨κ³Όλ‘ μ νμ΄ λ λΉ λ₯Ό λλ μμ |
10-2. μμ΅λΆκΈ°μ β μ λ ¬ν΄μΌ μ΄λμΈκ°
μ‘°νλ₯Ό kλ² νλ€κ³ κ°μ νκ³ λ μ λ΅ λΉμ©μ λΉκ΅ν©λλ€.
1
2
(A) λ§€λ² find : k * O(n) = O(kΒ·n)
(B) μ λ ¬ 1ν + binary_search kλ² : O(n log n) + k * O(log n)
(B) < (A) κ° λλ €λ©΄ λλ΅ k > log n μΌ λλΆν°. n=10βΆμ΄λ©΄ logβn β 20 β 20λ² λκ² μ‘°ννλ€λ©΄ μ λ ¬μ΄ μ΄λ. λ°λλ‘ νλ λ²λ§ μ°Ύκ³ λλλ©΄ κ·Έλ₯ findκ° λΉ λ¦
λλ€.
1
2
3
4
5
6
7
// μ μ’μ ν¨ν΄ β ν λ² μ°Ύμ κ±΄λ° μ λ ¬λΆν° ν¨
std::sort(v.begin(), v.end()); // O(n log n)
bool ok = std::binary_search(v.begin(), v.end(), x); // O(log n)
// ν©κ³ O(n log n) > std::findμ O(n)
// μ’μ ν¨ν΄ β μΌνμ±μ΄λ©΄ κ·Έλ₯ find
auto it = std::find(v.begin(), v.end(), x); // O(n)
10-3. μΊμ μΉνμ± β μμ λ°μ΄ν°μμ μ νμ΄ λΉ λ₯Ό μ μλ€
μκ³ λ¦¬μ¦ λ³΅μ‘λμ λ³κ°λ‘ λ©λͺ¨λ¦¬ μ κ·Ό ν¨ν΄μ΄ μ€μ μλλ₯Ό κ°λ₯Έλ€. ν° λ°μ΄ν°μμ λ¨μ λΉκ΅ νμλ§ λ³΄λ©΄ binary_searchκ° μμΉμ΄μ§λ§, λ°μ΄ν°κ° μμ L1/L2 μΊμμ λ€ μ¬λΌκ°λ κ²½μ°μ μ νμ΄ λ λΉ λ₯Ό μ μμ΅λλ€.
| μΈ‘λ©΄ | μ ν νμ (find) | μ΄λΆ νμ (binary_search) |
|---|---|---|
| λ©λͺ¨λ¦¬ μ κ·Ό | μμ°¨ β prefetcher νμ© | 무μμ μ ν β μΊμ λ―Έμ€ ε€ |
| λΆκΈ° μμΈ‘ | λ¨μ (!= lastλ§) | λΆκΈ° ε€ (mid λΉκ΅λ§λ€) |
| nμ΄ μμ λ | λΉ λ¦ (μλ°±~μμ² λ¨μ) | μ€λ²ν€λκ° μ΄λλ³΄λ€ νΌ |
| nμ΄ ν΄ λ | O(n) β μλμ μΌλ‘ λλ¦Ό | μλμ μΌλ‘ λΉ λ¦ |
μμ΅λΆκΈ° μ²΄κ° (λλ΅):
- n < μ½ 64~128 β μ νμ΄ λ λΉ λ₯΄κ±°λ λΉμ· (CPUΒ·νμ μ λ°λΌ λ€λ¦)
- n > μ½ 1,000 β μ΄λΆ νμμ΄ λͺ νν μ΄λ
- n > 100,000 β μ΄λΆ μμΉ, μ νμ μ¬μ€μ λͺ» μ
β κ·Έλμ νμ€ λΌμ΄λΈλ¬λ¦¬λ€μ΄ μμ ꡬκ°μμ μ νμΌλ‘ ν΄λ°±νλ νμ΄λΈλ¦¬λ μ λ ¬(introsort + insertion sort)μ μ°λ κ²κ³Ό κ°μ μ리.
10-4. nμ΄ μ λ§ ν΄ λ β μλ£κ΅¬μ‘°λ₯Ό μμ¬νλΌ
vectorμμ binary_search μΉ΄λλ§ λ§μ§μκ±°λ¦¬μ§ λ§κ³ , μ‘°νκ° ν΅μ¬ μν¬λ‘λλΌλ©΄ μλ£κ΅¬μ‘° μ체λ₯Ό λ°κΎΈλ κ² λ³΄ν΅ λ ν° μ°¨μ΄λ₯Ό λ§λλλ€.
| μλ£κ΅¬μ‘° | νκ· μ‘°ν | λΉκ³ |
|---|---|---|
μ λ ¬λ vector + binary_search | O(log n) | μΊμ μΉνμ , λ©λͺ¨λ¦¬ μ»΄ν©νΈ, μ½μ μ O(n) |
std::set / std::map (RB-Tree) | O(log n) | μ½μ Β·μμ O(log n), λ©λͺ¨λ¦¬ λ¨νΈν |
std::unordered_set / unordered_map | νκ· O(1) | ν΄μ. λ°μ΄ν° λ§€μ° ν΄ λ 1μμ |
| μΈλΆ μμΈ (B-Tree, Trie) | μΌμ΄μ€λ³ | DBΒ·νμΌ μμ€ν Β·λ¬Έμμ΄ |
β βμ λ ¬λ vector + binary_searchβλ λ©λͺ¨λ¦¬ ν¨μ¨κ³Ό μΊμ μΉνμ±μΌλ‘ μ’
μ’
setλ³΄λ€ λΉ λ¦
λλ€. μ μ λ°μ΄ν°(ν λ² λΉλ ν μ‘°νλ§)μ νΉν μ 리. β λμ μ½μ
μ΄ μ¦μΌλ©΄ unordered_set λλ set μ ν.
10-5. μ€μ κ°μ΄λ β μμ¬κ²°μ νλ¦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
νμμ΄ νμνλ€
β
βββββββββββββββ΄ββββββββββββββ
λ°μ΄ν° μ λ ¬λ¨? μλμ€
β β
μ ββββββββββββ΄βββββββββββ
β μ‘°νκ° 1~λͺ λ² μ‘°νκ° λ§μ(k > log n)
β β β
βββββββββ΄ββββββββ find μλ£κ΅¬μ‘°λ₯Ό λ°κΏ μ μλ?
μμΉ νμ? μ‘΄μ¬λ§? (O(n)) β
β β βββββββββββββ΄βββββββββ
lower_bound binary_search μ μλμ€
(O(log n)) (O(log n)) β β
unordered_set sort + binary_search
/map (O(1)) (O(n log n + k log n))
10-6. μμ£Ό νλ μ€μ
- βν° λ°μ΄ν°λκΉ λ¬΄μ‘°κ±΄ binary_searchβ β μ λ ¬ λΉμ©μ λΉΌλ¨Ήμ. μ λ ¬ μ λ λ°μ΄ν°λ₯Ό ν λ²λ§ μ°Ύμ κ±°λ©΄
findκ° μ λ΅. vectorμ λ§€λ²sortνΈμΆνκ³binary_searchβsortμμ²΄κ° O(n log n).setμ΄λunordered_setμ μ²μλΆν° μ°λ κ² λ§μ.listμbinary_searchβ Random Accessκ° μλλΌ μ νκ° O(n). μ΄λΆμ μ΄λ 0.listμ κ·Έλ₯find.- μ°κ΄ 컨ν
μ΄λμ μκ³ λ¦¬μ¦
std::findβset/map::findλ©€λ² ν¨μκ° O(log n) 보μ₯. μκ³ λ¦¬μ¦std::findλ O(n)μ΄λΌ μν΄ νΌ.
10-7. ν μ€ μμ½
1
2
3
4
5
ν° λ°μ΄ν° + μ λ ¬λ¨ β binary_search (O(log n)) β μμΉ
ν° λ°μ΄ν° + μ λ ¬ μ λ¨ + 1ν β find (O(n)) β μ λ ¬ λΉμ© ννΌ
ν° λ°μ΄ν° + μ λ ¬ μ λ¨ + λ€ν β sort + binary_search β k > log nμμ μ΄λ
κ±°λ λ°μ΄ν° + μ‘°ν λΉλ² β unordered_set/map (O(1)) β μλ£κ΅¬μ‘° κ΅μ²΄κ° μ λ΅
μμ λ°μ΄ν° (~μλ°±) β findλ μΆ©λΆ (μΊμΒ·λΆκΈ° μμΈ‘ μ΄μ )
β ν΅μ¬μ βμ λ ¬ λΉμ© + μ‘°ν λΉμ©βμ ν©μ³μ λΉκ΅ν κ², κ·Έλ¦¬κ³ μ§μ§ ν° λ°μ΄ν°λ©΄ μλ£κ΅¬μ‘° μ체λ₯Ό μμ¬ν κ².
μ 리 β μΈμ 무μμ μ°λ
1
2
3
4
5
6
μ λ ¬ μ λκ±°λ, μΌνμ±, equality λΉκ΅ μΆ©λΆ β std::find
μ λ ¬λκ³ , μ‘΄μ¬ μ¬λΆλ§ νμ β std::binary_search
μ λ ¬λκ³ , μμΉκΉμ§ νμ β std::lower_bound (+ *it == value κ²μ¬)
μ λ ¬λκ³ , κ°μ κ° λ²μ(μ€λ³΅ λ€ν) νμ β std::equal_range
μ λ ¬ μ μ§ μ½μ
β std::lower_bound + insert
μ°κ΄ 컨ν
μ΄λ (set/map/unordered_*) β λ©€λ² ν¨μ .find() β
μκ³ λ¦¬μ¦ X
ν΅μ¬ μμ½ μΉ΄λ (μ¬κ²μ¬)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::find β O(n), iterator, μ λ ¬ X, == | λͺ» μ°ΎμΌλ©΄ end()
std::binary_search β O(log n), bool, μ λ ¬ β
, <λ λ² | μμΉ λͺ¨λ¦
β μμΉκΉμ§ νμνλ©΄
std::lower_bound β O(log n), iterator (binary_search λ΄λΆ)
| λͺ» μ°Ύμλ end()κ° μλ μ μμ β *it == value μΆκ° κ²μ¬
iterator = 컨ν
μ΄λ μμλ₯Ό κ°λ¦¬ν€λ μΆμ ν¬μΈν°. *it / ++it / it==end 3μ’
end()λ past-the-end (μ ν¨ μμ μλ). [first, last) λ°μ΄λ¦° ꡬκ°.
λμΉ(equivalence) = !(a<b)&&!(b<a). ==κ³Ό λ€λ¦. < λ§ μ μλλ©΄ OK (strict weak ordering)
set/map β λ©€λ² ν¨μ find() (O(log n))
unordered_map β λ©€λ² ν¨μ find() (O(1) νκ· )
μκ³ λ¦¬μ¦ std::findμ μ°κ΄ 컨ν
μ΄λμ μ°λ©΄ μν΄ (O(n))
μΈλ¦¬μΌ: Algo::Find (T*), Algo::BinarySearch (int32 / INDEX_NONE),
TArray::Find (λ©€λ², int32)