πŸ€–/μ•Œκ³ λ¦¬μ¦˜ 정리

이진 탐색 μ•Œκ³ λ¦¬μ¦˜ (Binary Search Algorithm)

sssbin 2022. 2. 10. 21:57

 

순차 탐색

- 리슀트 μ•ˆμ— μžˆλŠ” νŠΉμ •ν•œ 데이터λ₯Ό μ°ΎκΈ° μœ„ν•΄ μ•žμ—μ„œλΆ€ν„° 데이터λ₯Ό ν•˜λ‚˜μ”© μ°¨λ‘€λŒ€λ‘œ ν™•μΈν•˜λŠ” 방법

- 보톡 μ •λ ¬λ˜μ§€ μ•Šμ€ λ¦¬μŠ€νŠΈμ—μ„œ 데이터λ₯Ό μ°Ύμ•„μ•Ό ν•  λ•Œ μ‚¬μš©

- 데이터 μ •λ ¬ 여뢀와 상관 없이 κ°€μž₯ μ•žμ— μžˆλŠ” μ›μ†ŒλΆ€ν„° ν•˜λ‚˜μ”© 확인

- μ‹œκ°„ λ³΅μž‘λ„ O(N)

    γ„΄ λ°μ΄ν„°μ˜ κ°œμˆ˜κ°€ N개일 λ•Œ μ΅œλŒ€ N번의 비ꡐ μ—°μ‚°

# 순차 탐색

def sequential_search(n, target, array):
    # 각 μ›μ†Œλ₯Ό ν•˜λ‚˜μ”© ν™•μΈν•˜λ©°
    for i in range(n):
        # ν˜„μž¬μ˜ μ›μ†Œκ°€ 찾고자 ν•˜λŠ” μ›μ†Œμ™€ λ™μΌν•œ 경우
        if array[i] == target:
            return i + 1    # ν˜„μž¬μ˜ μœ„μΉ˜ λ°˜ν™˜

print("생성할 μ›μ†Œ 개수λ₯Ό μž…λ ₯ν•œ λ‹€μŒ ν•œ μΉΈ 띄고 찾을 λ¬Έμžμ—΄μ„ μž…λ ₯ν•˜μ„Έμš”.")
input_data = input().split()
n = int(input_data[0])  # μ›μ†Œμ˜ 개수
target = input_data[1]  # 찾고자 ν•˜λŠ” λ¬Έμžμ—΄

print("μ•žμ„œ 적은 μ›μ†Œ 개수만큼 λ¬Έμžμ—΄μ„ μž…λ ₯ν•˜μ„Έμš”. ꡬ뢄은 띄어쓰기 ν•œ 칸으둜 ν•©λ‹ˆλ‹€.")
array = input().split()

# 순차 탐색 μˆ˜ν–‰ κ²°κ³Ό 좜λ ₯
print(sequential_search(n, target, array))

 

 

이진 탐색

- λ°°μ—΄ λ‚΄λΆ€μ˜ 데이터가 μ •λ ¬λ˜μ–΄ μžˆμ–΄μ•Όλ§Œ μ‚¬μš©ν•  수 μžˆλŠ” μ•Œκ³ λ¦¬μ¦˜

- 탐색 λ²”μœ„λ₯Ό μ ˆλ°˜μ”© μ’ν˜€κ°€λ©° 데이터λ₯Ό 탐색

- μ°ΎμœΌλ €λŠ” 데이터와 쀑간점 μœ„μΉ˜μ— μžˆλŠ” 데이터λ₯Ό 반볡적으둜 비ꡐ

- μ‹œκ°„ λ³΅μž‘λ„ O(logN) 

    γ„΄ ν•œ 번 확인할 λ•Œλ§ˆλ‹€ ν™•μΈν•˜λŠ” μ›μ†Œμ˜ κ°œμˆ˜κ°€ μ ˆλ°˜μ”© 쀄어듦.

# μž¬κ·€ ν•¨μˆ˜λ‘œ κ΅¬ν˜„ν•œ 이진 탐색

def binary_search(array, target, start, end):
    if start > end:
        return None
    
    mid = (start + end) // 2
    
    # 찾은 경우 쀑간점 인덱슀 λ°˜ν™˜
    if array[mid] == target:
        return mid
    # μ€‘κ°„μ μ˜ 값보닀 찾고자 ν•˜λŠ” 값이 μž‘μ€ 경우 μ™Όμͺ½ 확인
    elif array[mid] > target:
        return binary_search(array, target, start, mid-1)
    # μ€‘κ°„μ μ˜ 값보닀 찾고자 ν•˜λŠ” 값이 큰 경우 였λ₯Έμͺ½ 확인
    else:
        return binary_search(array, target, mid+1, end)

n, target = list(map(int, input().split()))
array = list(map(int, input().split()))

result = binary_search(array, target, 0, n-1)
if result == None:
    print("μ›μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.")
else:
    print(result+1)
# 반볡문으둜 κ΅¬ν˜„ν•œ 이진 탐색

def binary_search(array, target, start, end):
    while start <= end:
        mid = (start + end) // 2

        # 찾은 경우 쀑간점 인덱슀 λ°˜ν™˜
        if array[mid] == target:
            return mid
        # μ€‘κ°„μ μ˜ 값보닀 찾고자 ν•˜λŠ” 값이 μž‘μ€ 경우 μ™Όμͺ½ 확인
        elif array[mid] > target:
            end = mid - 1
        # μ€‘κ°„μ μ˜ 값보닀 찾고자 ν•˜λŠ” 값이 큰 경우 였λ₯Έμͺ½ 확인
        else:
            start = mid + 1

    return None

n, target = list(map(int, input().split()))
array = list(map(int, input().split()))

result = binary_search(array, target, 0, n-1)
if result == None:
    print("μ›μ†Œκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.")
else:
    print(result+1)

 

                                                                                                                                                                                                                                                                                                 

트리 자료ꡬ쑰

- λ…Έλ“œμ™€ λ…Έλ“œμ˜ μ—°κ²°λ‘œ ν‘œν˜„

- κ·Έλž˜ν”„ 자료ꡬ쑰의 μΌμ’…μœΌλ‘œ λ°μ΄ν„°λ² μ΄μŠ€ μ‹œμŠ€ν…œμ΄λ‚˜ νŒŒμΌμ‹œμŠ€ν…œκ³Ό 같은 κ³³μ—μ„œ λ§Žμ€ μ–‘μ˜ 데이터λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ λͺ©μ μœΌλ‘œ μ‚¬μš©

 

 

- νŠΈλ¦¬λŠ” λΆ€λͺ¨ λ…Έλ“œμ™€ μžμ‹ λ…Έλ“œμ˜ κ΄€κ³„λ‘œ ν‘œν˜„λœλ‹€.

- 트리의 μ΅œμƒλ‹¨ λ…Έλ“œλ₯Ό 루트 λ…Έλ“œλΌκ³  ν•œλ‹€.

- 트리의 μ΅œν•˜λ‹¨ λ…Έλ“œλ₯Ό 단말 λ…Έλ“œλΌκ³  ν•œλ‹€.

- νŠΈλ¦¬μ—μ„œ 일뢀λ₯Ό 떼어내도 트리 ꡬ쑰이며 이λ₯Ό μ„œλΈŒ 트리라 ν•œλ‹€.

- νŠΈλ¦¬λŠ” 계측적이고 μ •λ ¬λœ 데이터λ₯Ό 닀루기에 μ ν•©ν•˜λ‹€.

 

 

 

 

이진 탐색 트리

- λΆ€λͺ¨ λ…Έλ“œλ³΄λ‹€ μ™Όμͺ½ μžμ‹ λ…Έλ“œκ°€ μž‘λ‹€.

- λΆ€λͺ¨ λ…Έλ“œλ³΄λ‹€ 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œκ°€ 크닀.

 

- 이진 탐색 λ¬Έμ œλŠ” μž…λ ₯ 데이터가 λ§Žκ±°λ‚˜, 탐색 λ²”μœ„κ°€ 맀우 넓은 편.

- λ”°λΌμ„œ sys 라이브러리의 readline() ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μž.

 

 

μ‹€μ „ 문제1. λΆ€ν’ˆ μ°ΎκΈ° 

1) λ‚΄ μ½”λ“œ: 이진 탐색을 λ°˜λ³΅λ¬Έμ„ μ΄μš©ν•΄μ„œ ν’€μ—ˆμŒ.

# μ‹€μ „ 문제1. λΆ€ν’ˆ μ°ΎκΈ°

n = int(input())
n_array = list(map(int, input().split()))
m = int(input())
m_array = list(map(int, input().split()))

n_array.sort()

def binary_search(start, end, target):
    while start <= end:
        mid = (start + end) // 2

        if n_array[mid] == target:
            return True
        elif n_array[mid] < target:
            start = mid + 1
        else:
            end = mid - 1

    return False

for i in m_array:
    if binary_search(0, n-1, i):
        print('yes', end=' ')
    else:
        print('no', end=' ')

2) ꡐ재 μ½”λ“œ

# μ‹€μ „ 문제1. λΆ€ν’ˆ μ°ΎκΈ°
# ꡐ재 μ½”λ“œ - κ³„μˆ˜ μ •λ ¬

n = int(input())
array = [0] * 1000001

# κ°€κ²Œμ— μžˆλŠ” 전체 λΆ€ν’ˆ 번호λ₯Ό μž…λ ₯λ°›μ•„μ„œ 기둝
for i in input().split():
    array[int(i)] = 1

m = int(input())
x = list(map(int, input().split()))

# μ†λ‹˜μ΄ 확인 μš”μ²­ν•œ λΆ€ν’ˆ 번호λ₯Ό ν•˜λ‚˜μ”© 확인
for i in x:
    # ν•΄λ‹Ή λΆ€ν’ˆμ΄ μ‘΄μž¬ν•˜λŠ”μ§€ 확인
    if array[i] == 1:
        print('yes', end=' ')
    else:
        print('no', end=' ')

- λͺ¨λ“  μ›μ†Œμ˜ 번호λ₯Ό 포함할 수 μžˆλŠ” 크기의 리슀트λ₯Ό λ§Œλ“¦.

- 리슀트의 μΈλ±μŠ€μ— 직접 μ ‘κ·Όν•˜μ—¬ νŠΉμ •ν•œ 번호의 λΆ€ν’ˆμ΄ λ§€μž₯에 μ‘΄μž¬ν•˜λŠ”μ§€ 확인

# μ‹€μ „ 문제1. λΆ€ν’ˆ μ°ΎκΈ°
# ꡐ재 μ½”λ“œ - μ§‘ν•© μžλ£Œν˜• 이용

n = int(input())
array = set(map(int, input().split()))

m = int(input())
x = list(map(int, input().split()))

for i in x:
    if i in array:
        print('yes', end=' ')
    else:
        print('no', end=' ')

- λ‹¨μˆœνžˆ νŠΉμ •ν•œ μˆ˜κ°€ ν•œ λ²ˆμ΄λΌλ„ λ“±μž₯ν–ˆλŠ”μ§€λ₯Ό κ²€μ‚¬ν•˜λ©΄ 됨. -> μ§‘ν•© μžλ£Œν˜• 이용

 

 

μ‹€μ „ 문제2. 떑볢이 λ–‘ λ§Œλ“€κΈ°

# 이진 탐색
# μ‹€μ „ 문제2. 떑볢이 λ–‘ λ§Œλ“€κΈ°

n, m = map(int, input().split())
array = list(map(int, input().split()))

start = 0
end = max(array)

result = 0
while (start <= end):
    total = 0
    mid = (start + end) // 2

    # μž˜λžμ„ λ•Œ λ–‘μ˜ μ–‘ 계산
    for i in array:
        if i > mid:
            total += i - mid

    # λ–‘μ˜ 양이 λΆ€μ‘±ν•œ 경우 더 많이 자λ₯΄κΈ° (μ™Όμͺ½ λΆ€λΆ„ 탐색)
    if total < m:
        end = mid - 1
    # λ–‘μ˜ 양이 μΆ©λΆ„ν•œ 경우 덜 자λ₯΄κΈ° (였λ₯Έμͺ½ λΆ€λΆ„ 탐색)
    else:
        result = mid    # μ΅œλŒ€ν•œ 덜 μž˜λžμ„ λ•Œκ°€ μ •λ‹΅μ΄λ―€λ‘œ, μ—¬κΈ°μ—μ„œ result에 기둝
        start = mid + 1

print(result)

- νŒŒλΌλ©”νŠΈλ¦­ μ„œμΉ˜: μ΅œμ ν™” 문제λ₯Ό κ²°μ • 문제둜 λ°”κΎΈμ–΄ ν•΄κ²°

- λ²”μœ„ λ‚΄μ—μ„œ 쑰건을 λ§Œμ‘±ν•˜λŠ” κ°€μž₯ 큰 값을 μ°ΎμœΌλΌλŠ” μ΅œμ ν™” 문제라면 이진 νƒμƒ‰μœΌλ‘œ κ²°μ • 문제λ₯Ό ν•΄κ²°ν•˜λ©΄μ„œ λ²”μœ„λ₯Ό μ’ν˜€κ°ˆ 수 μžˆλ‹€.

- μ μ ˆν•œ 높이λ₯Ό 찾을 λ•ŒκΉŒμ§€ μ ˆλ‹¨κΈ°μ˜ 높이 Hλ₯Ό 반볡적으둜 μ‘°μ •ν•œλ‹€.

- κ·Έλž˜μ„œ 'ν˜„μž¬ 이 λ†’μ΄λ‘œ 자λ₯΄λ©΄ 쑰건을 λ§Œμ‘±ν•  수 μžˆλŠ”κ°€?'λ₯Ό ν™•μΈν•œ λ’€ 쑰건의 만쑱 여뢀에 따라 탐색 λ²”μœ„λ₯Ό μ’ν˜€κ°„λ‹€.