ํฌ์ŠคํŠธ

CS โ€” find vs binary search

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 ๋ฒˆ ๋น„๊ต
๋ฐ˜ํ™˜ ํƒ€์ž…iteratorfind โ€” ์œ„์น˜ ์ •๋ณด (๋ชป ์ฐพ์œผ๋ฉด last)
ย boolbinary_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::findRB-Tree O(log n) ๋ฉค๋ฒ„ ํ•จ์ˆ˜ โ€” ๋ฐ˜๋“œ์‹œ ์ด๊ฑธ ์”€
ย unordered_map::findํ•ด์‹œ ํ‰๊ท  O(1) ๋ฉค๋ฒ„ ํ•จ์ˆ˜
ย ์•Œ๊ณ ๋ฆฌ์ฆ˜ std::find์ปจํ…Œ์ด๋„ˆ ๊ตฌ์กฐ ๋ฌด์‹œ O(n) โ€” ์—ฐ๊ด€ ์ปจํ…Œ์ด๋„ˆ์— ์“ฐ๋ฉด ์†ํ•ด
ํ•จ์ •์ •๋ ฌ ์•ˆ ๋œ ์ปจํ…Œ์ด๋„ˆ + binary_search๋ฏธ์ •์˜ ๋™์ž‘ (UB)
ย strict weak ordering ๊นจ์ง๋น„๊ต์ž๊ฐ€ ์ž˜๋ชป๋˜๋ฉด binary_search ๊ฒฐ๊ณผ ๋ณด์žฅ ์•ˆ ๋จ
์–ธ๋ฆฌ์–ผAlgo::Findstd::find ๋Œ€์‘ (์„ ํ˜•)
ย Algo::BinarySearchstd::binary_search ๋Œ€์‘. int32 ์ธ๋ฑ์Šค ๋ฐ˜ํ™˜ (INDEX_NONE = -1)
ย TArray::Find๋ฉค๋ฒ„ ํ•จ์ˆ˜. ์ธ๋ฑ์Šค ๋ฐ˜ํ™˜

๋ชฉ์ฐจ

  1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ
  2. std::find โ€” ์„ ํ˜• ํƒ์ƒ‰
  3. std::binary_search โ€” ์ด๋ถ„ ํƒ์ƒ‰
  4. ํ•ต์‹ฌ ์ฐจ์ด์  5๊ฐ€์ง€
  5. ๊ด€๋ จ ์•Œ๊ณ ๋ฆฌ์ฆ˜ family โ€” lower_bound / upper_bound / equal_range
  6. ์ฝ”๋“œ ๋น„๊ต โ€” vector ๊ธฐ๋ฐ˜
  7. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ
  8. ์–ธ๋ฆฌ์–ผ์—์„œ์˜ ํƒ์ƒ‰ โ€” Algo::Find / Algo::BinarySearch
  9. ๋ณด๊ฐ• โ€” iterator ยท ๋™์น˜ํŒ๋‹จ ยท lower_bound vs find
  10. ๋ณด๊ฐ• โ€” ํฐ ๋ฐ์ดํ„ฐ์—์„œ 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::findstd::binary_search
์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ˜• ํƒ์ƒ‰์ด๋ถ„ ํƒ์ƒ‰
์‹œ๊ฐ„๋ณต์žก๋„O(n)O(log n) (๋น„๊ต ํšŸ์ˆ˜ ๊ธฐ์ค€)
์‚ฌ์ „ ์ •๋ ฌ๋ถˆํ•„์š”ํ•„์ˆ˜ (์•ˆ ๋˜๋ฉด UB)
๋ฐ˜ํ™˜ ํƒ€์ž…Iterator (์œ„์น˜)bool (์กด์žฌ ์—ฌ๋ถ€๋งŒ)
๋น„๊ต ์—ฐ์‚ฐ์ž== (equality)< ๋‘ ๋ฒˆ (strict weak ordering)
์š”๊ตฌ iteratorInputIteratorForwardIterator (์‹คํšจ๋Š” 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_searchbool์กด์žฌ ์—ฌ๋ถ€๋งŒ๋‚ด๋ถ€๋Š” lower_bound
lower_bounditeratorvalue ์ด์ƒ ์ฒซ ์œ„์น˜์‚ฝ์ž… ์œ„์น˜ ๊ฒฐ์ •์—๋„ ์‚ฌ์šฉ
upper_bounditeratorvalue ์ดˆ๊ณผ ์ฒซ ์œ„์น˜lower_bound์™€ ์Œ
equal_rangepair<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::findAlgo::Find(Arr, Value)T* (๋ชป ์ฐพ์œผ๋ฉด nullptr)
std::find_ifAlgo::FindByPredicateT*
std::binary_searchAlgo::BinarySearch(Arr, Value)int32 ์ธ๋ฑ์Šค (๋ชป ์ฐพ์œผ๋ฉด INDEX_NONE = -1)
std::lower_boundAlgo::LowerBoundint32
std::upper_boundAlgo::UpperBoundint32
std::sortAlgo::Sortvoid
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 < it2vector, 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)iteratorlast (= end())
std::string::findsize_tstd::string::npos (= -1์„ unsigned๋กœ)
TArray::Find (Unreal)int32 ์ธ๋ฑ์ŠคINDEX_NONE (= -1)
Algo::Find (Unreal)T* ํฌ์ธํ„ฐnullptr
std::map::find (๋ฉค๋ฒ„)iteratorend()

โ†’ โ€œ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::findstd::lower_bound
์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ˜•์ด๋ถ„
์ •๋ ฌ ์ „์ œ๋ถˆํ•„์š”ํ•„์ˆ˜
์‹œ๊ฐ„๋ณต์žก๋„O(n)O(log n)
๋น„๊ต ์—ฐ์‚ฐ์ž==<
๋ฐ˜ํ™˜์ผ์น˜ํ•˜๋Š” ์ฒซ iteratorvalue ์ด์ƒ์ธ ์ฒซ iterator
๋ชป ์ฐพ์„ ๋•Œ ๋ฐ˜ํ™˜last (๋ช…ํ™•)last ๋˜๋Š” value๋ณด๋‹ค ํฐ ๋‹ค๋ฅธ ์œ„์น˜ (์ถ”๊ฐ€ ๊ฒ€์‚ฌ ํ•„์š”)
๋ถ€๊ฐ€ ์šฉ๋„์œ„์น˜ ์ฐพ๊ธฐ๋งŒ์ •๋ ฌ ์œ ์ง€ ์‚ฝ์ž… ์œ„์น˜ ๊ณ„์‚ฐ
iterator ์š”๊ตฌInputIteratorForwardIterator (์‹คํšจ 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_searchO(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)
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

ยฉ GoldBoll. ์ผ๋ถ€ ๊ถŒ๋ฆฌ ๋ณด์œ 

Powered by Jekyll with Chirpy theme

์ธ๊ธฐ ํƒœ๊ทธ