๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“š Computer Science/Algorithm

[์•Œ๊ณ ๋ฆฌ์ฆ˜] ์ด์ง„ ํƒ์ƒ‰(Binary Search)

by hyebin (Helia) 2022. 3. 25.
๋ฐ˜์‘ํ˜•

์ˆœ์ฐจ ํƒ์ƒ‰(Sequential Search)

  • ๋ฆฌ์ŠคํŠธ ์•ˆ์— ์žˆ๋Š” ํŠน์ •ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ์•ž์—์„œ๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์ฐจ๋ก€๋Œ€๋กœ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ์ •๋ ฌ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ๊ฐ€์žฅ ์•ž์—์„œ๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ํ™•์ธ
  • ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๋ฆฌ์ŠคํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ
  • ๋ฆฌ์ŠคํŠธ ๋‚ด์— ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋ฌด๋ฆฌ ๋งŽ์•„๋„ ์‹œ๊ฐ„๋งŒ ์ถฉ๋ถ„ํ•˜๋‹ค๋ฉด ํ•ญ์ƒ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ → O(N)

์ด์ง„ ํƒ์ƒ‰(Binary Search)

  • ํƒ์ƒ‰ ๋ฒ”์œ„๋ฅผ ์ ˆ๋ฐ˜์”ฉ ์ขํ˜€๊ฐ€๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ํƒ์ƒ‰
  • ์ฐพ์œผ๋ ค๋Š” ๋ฐ์ดํ„ฐ์™€ ์ค‘๊ฐ„์  ์œ„์น˜์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋น„๊ตํ•˜์—ฌ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํƒ์ƒ‰
  • ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์‹œ์ž‘์ , ๋์ , ์ค‘๊ฐ„์  3๊ฐœ์˜ ๋ณ€์ˆ˜ ์‚ฌ์šฉ
  • ๋ฐฐ์—ด ๋‚ด๋ถ€์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์ •๋ ฌ๋˜์–ด ์žˆ์–ด์•ผ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ → O(logN)

 

ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ

๋”๋ณด๊ธฐ

ํŠธ๋ฆฌ(Tree) ๊ตฌ์กฐ

  • ๋…ธ๋“œ์™€ ๋…ธ๋“œ์˜ ์—ฐ๊ฒฐ๋กœ ํ‘œํ˜„ ( ๋…ธ๋“œ: ์ •๋ณด์˜ ๋‹จ์œ„, ์–ด๋– ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐœ์ฒด)
  • ๊ทธ๋ž˜ํ”„ ์ž๋ฃŒ๊ตฌ์กฐ์˜ ์ผ์ข…์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์ด๋‚˜ ํŒŒ์ผ ์‹œ์Šคํ…œ๊ณผ ๊ฐ™์€ ๊ณณ์—์„œ ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉ

ํŠธ๋ฆฌ ๊ตฌ์กฐ์˜ ํŠน์ง•

  • ํŠธ๋ฆฌ๋Š” ๋ถ€๋ชจ ๋…ธ๋“œ์™€ ์ž์‹ ๋…ธ๋“œ์˜ ๊ด€๊ณ„๋กœ ํ‘œํ˜„
  • ํŠธ๋ฆฌ์˜ ์ตœ์ƒ๋‹จ ๋…ธ๋“œ๋Š” ๋ฃจํŠธ ๋…ธ๋“œ
  • ํŠธ๋ฆฌ์˜ ์ตœํ•˜๋‹จ ๋…ธ๋“œ๋Š” ๋‹จ๋ง ๋…ธ๋“œ
  • ํŠธ๋ฆฌ์—์„œ ์ผ๋ถ€๋ฅผ ๋–ผ์–ด๋‚ด๋„ ํŠธ๋ฆฌ ๊ตฌ์กฐ์ด๋ฉฐ ์ด๋ฅผ ์„œ๋ธŒ ํŠธ๋ฆฌ๋ผ๊ณ  ํ•จ
  • ํŠธ๋ฆฌ๋Š” ํŒŒ์ผ ์‹œ์Šคํ…œ๊ณผ ๊ฐ™์ด ๊ณ„์ธต์ ์ด๊ณ  ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ์— ์ ํ•ฉ

โ˜ž ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด๋Š” ๋Œ€๋ถ€๋ถ„ ๋ฐ์ดํ„ฐ๋ฅผ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ์ €์žฅํ•ด ์ด์ง„ ํƒ์ƒ‰๊ณผ ๊ฐ™์€ ํƒ์ƒ‰ ๊ธฐ๋ฒ•์„ ์ด์šฉํ•ด ๋น ๋ฅด๊ฒŒ ํƒ์ƒ‰ ๊ฐ€๋Šฅ

 

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ

  • ํŠธ๋ฆฌ ์ž๋ฃŒ๊ตฌ์กฐ ์ค‘์—์„œ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํ˜•ํƒœ
  • ์ด์ง„ ํƒ์ƒ‰์ด ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ณ ์•ˆ๋œ, ํšจ์œจ์ ์ด๊ณ  ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•œ ์ž๋ฃŒ๊ตฌ์กฐ
  • ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ๋ฐฉ๋ฌธํ•˜์—ฌ ์ฐพ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฃจํŠธ ๋…ธ๋“œ ๊ฐ’ ๋ณด๋‹ค ํฌ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธํ•˜๊ณ , ์ž‘๋‹ค๋ฉด ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๋ฅผ ๋ฐฉ๋ฌธ
  • ๋ฐฉ๋ฌธํ•œ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ ๋…ธ๋“œ๊ฐ€ ๋˜์–ด ํฌ๊ธฐ๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋‹ค์Œ ๋ฐฉ๋ฌธํ•  ๋…ธ๋“œ ์„ ํƒ
  • ์ฐพ์œผ๋ ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ํŠน์ง•

  • ๋ถ€๋ชจ ๋…ธ๋“œ๋ณด๋‹ค ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ์ž‘๋‹ค
  • ๋ถ€๋ชจ ๋…ธ๋“œ๋ณด๋‹ค ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ๊ฐ€ ํฌ๋‹ค

 


์ด์ง„ ํƒ์ƒ‰ ๋ฌธ์ œ

๋ถ€ํ’ˆ  ์ฐพ๊ธฐ

๋™๋นˆ์ด๋„ค ์ „์ž ๋งค์žฅ์—๋Š” ๋ถ€ํ’ˆ์ด N๊ฐœ ์žˆ๋‹ค. ๊ฐ ๋ถ€ํ’ˆ์€ ์ •์ˆ˜ ํ˜•ํƒœ์˜ ๊ณ ์œ ํ•œ ๋ฒˆํ˜ธ๊ฐ€ ์žˆ๋‹ค.
์–ด๋А ๋‚  ์†๋‹˜์ด M๊ฐœ ์ข…๋ฅ˜์˜ ๋ถ€ํ’ˆ์„ ๋Œ€๋Ÿ‰์œผ๋กœ ๊ตฌ๋งคํ•˜๊ฒ ๋‹ค๋ฉฐ ๋‹น์ผ๋‚  ๊ฒฌ์ ์„œ๋ฅผ ์š”์ฒญํ–ˆ๋‹ค.
๋™๋นˆ์ด๋Š” ๋•Œ๋ฅผ ๋†“์น˜์ง€ ์•Š๊ณ  ์†๋‹˜์ด ๋ฌธ์˜ํ•œ ๋ถ€ํ’ˆ M๊ฐœ ์ข…๋ฅ˜๋ฅผ ๋ชจ๋‘ ํ™•์ธํ•ด์„œ ๊ฒฌ์ ์„œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.
์ด๋•Œ ๊ฐ€๊ฒŒ ์•ˆ์— ๋ถ€ํ’ˆ์ด ๋ชจ๋‘ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•ด๋ณด์ž. 

์ด์ง„ ํƒ์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ ์†Œ์Šค ์ฝ”๋“œ

// ์ด์ง„ ํƒ์ƒ‰
func binary_search(_ arr: [Int], _ target: Int, _ start: Int, _ end: Int) -> Bool{
    var s = start, e = end
    while s <= e{
        var mid = (s+e)/2
        
        if arr[mid] == target{ return true }
        else if arr[mid] > target{ e = mid-1 }
        else { s = mid + 1 }
    }
    return false
}

var n = Int(readLine()!)!
var n_arr = readLine()!.split(separator: " ").map{Int(String($0))!}
n_arr = n_arr.sorted()

var m = Int(readLine()!)!
var m_arr = readLine()!.split(separator: " ").map{Int(String($0))!}

for i in m_arr{
    binary_search(n_arr, i, 0, n-1) ? print("yse", terminator: " ") : print("no", terminator: " ")
}

๊ณ„์ˆ˜ ์ •๋ ฌ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•œ ์†Œ์Šค์ฝ”๋“œ

  • ๋ชจ๋“  ์›์†Œ์˜ ๋ฒˆํ˜ธ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ํฌ๊ธฐ์˜ ๋ฐฐ์—ด์„ ๋งŒ๋“  ํ›„, ๋ฐฐ์—ด ์ธ๋ฑ์Šค์— ์ง์ ‘ ์ ‘๊ทผํ•˜์—ฌ ํŠน์ • ๋ฒˆํ˜ธ์˜ ๋ถ€ํ’ˆ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
// ๊ณ„์ˆ˜ ์ •๋ ฌ
var n = Int(readLine()!)!
var n_arr: [Int] = Array(repeating: 0, count: 1000001)

for i in readLine()!.split(separator: " ").map{Int(String($0))!}{
    n_arr[i] = 1
}

var m = Int(readLine()!)!
var m_arr = readLine()!.split(separator: " ").map{Int(String($0))!}

for i in m_arr{
    if n_arr[i] == 1 { print("yes", terminator: " ") }
    else { print("no", terminator: " ") }
}

์ง‘ํ•ฉ ์ž๋ฃŒํ˜•์„ ์ด์šฉํ•œ ์†Œ์Šค ์ฝ”๋“œ

// Set(์ง‘ํ•ฉ)์ž๋ฃŒํ˜• ์‚ฌ์šฉ
var n = Int(readLine()!)!
var n_arr = Set(readLine()!.split(separator: " ").map{Int(String($0))!})

var m = Int(readLine()!)!
var m_arr = readLine()!.split(separator: " ").map{Int(String($0))!}

for i in m_arr{
    if n_arr.contains(i) { print("yes", terminator: " ") }
    else { print("no", terminator: " ") }
}

๋–ก๋ณถ์ด ๋–ก ๋งŒ๋“ค๊ธฐ

์˜ค๋Š˜ ๋™๋นˆ์ด๋Š” ์—ฌํ–‰ ๊ฐ€์‹  ๋ถ€๋ชจ๋‹˜์„ ๋Œ€์‹ ํ•ด์„œ ๋–ก์ง‘ ์ผ์„ ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ์˜ค๋Š˜์€ ๋–ก๋ณถ์ด ๋–ก์„ ๋งŒ๋“œ๋Š” ๋‚ ์ด๋‹ค.
๋™๋นˆ์ด๋„ค ๋–ก๋ณถ์ด ๋–ก์€ ์žฌ๋ฐŒ๊ฒŒ๋„ ๋–ก๋ณถ์ด ๋–ก์˜ ๊ธธ์ด๊ฐ€ ์ผ์ •ํ•˜์ง€ ์•Š๋‹ค. ๋Œ€์‹  ํ•œ ๋ด‰์ง€ ์•ˆ์— ๋“ค์–ด๊ฐ€๋Š” ๋–ก์˜ ์ด ๊ธธ์ด๋Š” ์ ˆ๋‹จ๊ธฐ๋กœ ์ž˜๋ผ์„œ ๋งž์ถ˜๋‹ค.
์ ˆ๋‹จ๊ธฐ ๋†’์ด(H)๋ฅผ ์ง€์ •ํ•˜๋ฉด ์ค„์ง€์–ด์ง„ ๋–ก์„ ํ•œ ๋ฒˆ์— ์ ˆ๋‹จํ•œ๋‹ค. ๋†’์ด๊ฐ€ H๋ณด๋‹ค ๊ธด ๋–ก์€ H ์œ„์˜ ๋ถ€๋ถ„์ด ์ž˜๋ฆด ๊ฒƒ์ด๊ณ , ๋‚ฎ์€ ๋–ก์„ ์ž˜๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.
์†๋‹˜์ด ์™”์„ ๋•Œ ์š”์ฒญํ•œ ์ด ๊ธธ์ด๊ฐ€ M ์ผ ๋•Œ, ์ ์–ด๋„ M ๋งŒํผ์˜ ๋–ก์„ ์–ป๊ธฐ ์œ„ํ•ด ์ ˆ๋‹จ๊ธฐ์— ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ๋†’์ด๋ฅผ ๊ตฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

ํŒŒ๋ผ๋ฉ”ํŠธ๋ฆญ ์„œ์น˜(Parametric Search) ์œ ํ˜• ๋ฌธ์ œ

  • ์ตœ์ ํ™” ๋ฌธ์ œ๋ฅผ ๊ฒฐ์ •๋ฌธ์ œ๋กœ ๋ฐ”๊พธ์–ด ํ•ด๊ฒฐํ•˜๋Š” ๊ธฐ๋ฒ•
    • ๊ฒฐ์ • ๋ฌธ์ œ - "์˜ˆ" ํ˜น์€ "์•„๋‹ˆ์˜ค"๋กœ ๋‹ตํ•˜๋Š” ๋ฌธ์ œ
  • ์›ํ•˜๋Š” ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฐ€์žฅ ์•Œ๋งž์€ ๊ฐ’์„ ์ฐพ๋Š” ๋ฌธ์ œ์— ์ฃผ๋กœ ์‚ฌ์šฉ
  • ex) ๋ฒ”์œ„ ๋‚ด์—์„œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ์ฐพ๋Š” ๋ฌธ์ œ
var input_data = readLine()!.split(separator: " ").map{Int(String($0))!}
var n = input_data[0], m = input_data[1]
var arr = readLine()!.split(separator: " ").map{Int(String($0))!}

var start = 0, end = arr.max()!

var re = 0
while start <= end{
    var total = 0
    var mid = (start+end)/2
    
    for x in arr{
        if x > mid { total += x - mid }
    }
    if total < m { end = mid - 1}
    else{
        re = mid
        start = mid + 1
    }
}
print(re)
๋ฐ˜์‘ํ˜•