πŸ€“ 이진탐색 μ•Œκ³ λ¦¬μ¦˜

yeeun leeΒ·2020λ…„ 7μ›” 6일
2

이진 탐색은 검색 μ•Œκ³ λ¦¬μ¦˜ 쀑 ν•˜λ‚˜λ‘œ, μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬λ˜μ–΄ μžˆλŠ” λ°°μ—΄μ—μ„œ 값을 μ°ΎκΈ° μœ„ν•΄ 쀑간 값을 κΈ°μ€€μœΌλ‘œ κ°€λŠ₯성을 λ°˜μ”© 쀄여 target valueλ₯Ό νƒμƒ‰ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

κ°œλ…

이진 검색 μ•Œκ³ λ¦¬μ¦˜(binary search algorithm)은 μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬λœ λ¦¬μŠ€νŠΈμ—μ„œ νŠΉμ •ν•œ κ°’μ˜ μœ„μΉ˜λ₯Ό μ°ΎλŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

처음 μ€‘κ°„μ˜ 값을 μž„μ˜μ˜ κ°’μœΌλ‘œ μ„ νƒν•˜μ—¬, κ·Έ κ°’κ³Ό 찾고자 ν•˜λŠ” κ°’μ˜ 크고 μž‘μŒμ„ λΉ„κ΅ν•˜λŠ” 방식을 μ±„νƒν•˜κ³  μžˆλ‹€. 처음 μ„ νƒν•œ 쀑앙값이 λ§Œμ•½ μ°ΎλŠ” 값보닀 크면 κ·Έ 값은 μƒˆλ‘œμš΄ μ΅œλŒ“κ°’μ΄ 되며, μž‘μœΌλ©΄ κ·Έ 값은 μƒˆλ‘œμš΄ μ΅œμ†Ÿκ°’μ΄ λœλ‹€.

검색 원리상 μ •λ ¬λœ λ¦¬μŠ€νŠΈμ—λ§Œ μ‚¬μš©ν•  수 μžˆλ‹€λŠ” 단점이 μžˆμ§€λ§Œ, 검색이 반볡될 λ•Œλ§ˆλ‹€ λͺ©ν‘œκ°’을 찾을 ν™•λ₯ μ€ 두 λ°°κ°€ λ˜λ―€λ‘œ 속도가 λΉ λ₯΄λ‹€λŠ” μž₯점이 μžˆλ‹€. (μ°Έκ³ : μœ„ν‚€λ°±κ³Ό)

예제

μž¬κ·€ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•œ 이진탐색 ν•¨μˆ˜λ‹€. 어쩐지 λ­”κ°€ 반볡문처럼 Return을 인자만 λ°”κΎΌ 자기 μžμ‹ μ„ ν•΄μ„œ μ‹ κΈ°ν•˜λ‹€κ³  μƒκ°ν–ˆλŠ”λ°, 이름이 λ”°λ‘œ μžˆμ—ˆλ‹€. μž¬κ·€ν•¨μˆ˜ 외에도 λ°˜λ³΅λ¬Έμ„ ν†΅ν•΄μ„œ ꡬ할 수 μžˆλ‹€.

컴퓨터 과학에 μžˆμ–΄μ„œ μž¬κ·€λŠ” μžμ‹ μ„ μ •μ˜ν•  λ•Œ 자기 μžμ‹ μ„ μž¬μ°Έμ‘°ν•˜λŠ” 방법을 λœ»ν•˜λ©°, 이λ₯Ό ν”„λ‘œκ·Έλž˜λ°μ— μ μš©ν•œ μž¬κ·€ 호좜의 ν˜•νƒœλ‘œ 많이 μ‚¬μš©λœλ‹€. 또 μ‚¬μ§„μ΄λ‚˜ κ·Έλ¦Ό λ“±μ—μ„œ μž¬κ·€μ˜ ν˜•νƒœλ₯Ό μ‚¬μš©ν•˜λŠ” κ²½μš°λ„ μžˆλ‹€.

def binarySearch(array, value, low, high):
	if low > high:
		return False
	mid = (low+high) / 2
	if array[mid] > value:
		return binarySearch(array, value, low, mid-1)
	elif array[mid] < value:
		return binarySearch(array, value, mid+1, high)
	else:
		return mid

문제

N개의 μ •μˆ˜ A[1], A[2], …, A[N]이 μ£Όμ–΄μ Έ μžˆμ„ λ•Œ, 이 μ•ˆμ— XλΌλŠ” μ •μˆ˜κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ μ•Œμ•„λ‚΄λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

- μž…λ ₯

첫째 쀄에 μžμ—°μˆ˜ N(1≀N≀100,000)이 주어진닀. λ‹€μŒ μ€„μ—λŠ” N개의 μ •μˆ˜ A[1], A[2], …, A[N]이 주어진닀. λ‹€μŒ μ€„μ—λŠ” M(1≀M≀100,000)이 주어진닀. λ‹€μŒ μ€„μ—λŠ” M개의 μˆ˜λ“€μ΄ μ£Όμ–΄μ§€λŠ”λ°, 이 μˆ˜λ“€μ΄ Aμ•ˆμ— μ‘΄μž¬ν•˜λŠ”μ§€ μ•Œμ•„λ‚΄λ©΄ λœλ‹€. λͺ¨λ“  μ •μˆ˜μ˜ λ²”μœ„λŠ” -231 보닀 ν¬κ±°λ‚˜ κ°™κ³  231보닀 μž‘λ‹€.

5
4 1 5 2 3
5
1 3 7 9 5

- 좜λ ₯

M개의 쀄에 닡을 좜λ ₯ν•œλ‹€. μ‘΄μž¬ν•˜λ©΄ 1을, μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ 0을 좜λ ₯ν•œλ‹€.

1
1
0
0
1

- μ •λ‹΅

문제λ₯Ό μ΄ν•΄ν•˜λŠ”λ° μ‹œκ°„μ΄ 쑰금 κ±Έλ ΈλŠ”λ°, N은 λ‚΄κ°€ μˆ«μžκ°€ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό 확인해쀄 μ •λ‹΅ λ°°μ—΄μ˜ 길이, κ·Έ λ‹€μŒ 쀄은 1λΆ€ν„° NκΉŒμ§€μ˜ μˆ«μžκ°€ 랜덀으둜 μžˆλŠ” 배열이닀.

그리고 M은 λ‚΄κ°€ μžˆλŠ”μ§€ μ—¬λΆ€λ₯Ό 확인할 λ¬Έμ œλ“€μ΄ λͺ¨μ—¬μžˆλŠ” 배열이고, λ°˜λ³΅λ¬Έμ„ λŒλ €μ„œ μ •λ‹΅ λ°°μ—΄ μ•ˆμ— μžˆλŠ”μ§€ 확인할 숫자 듀이닀.

μ•„λž˜ μ½”λ“œλ₯Ό 보면 결과적으둜 μ •λ‹΅ 배열을 sorted ν•¨μˆ˜λ‘œ μ˜€λ¦„μ°¨μˆœ μ •λ ¬ν•΄μ€€ λ‹€μŒ, 문제 배열을 μ΄μ§„νƒμƒ‰μœΌλ‘œ λŒλ €μ„œ κ²°κ³Όλ₯Ό ν”„λ¦°νŠΈν•œλ‹€.

μ‹ κΈ°ν•œκ²Œ ν•¨μˆ˜λ₯Ό Returnν•˜λ©΄μ„œ μ •μ˜ν•œ λ³€μˆ˜λ₯Ό 인자둜 λ„£λŠ” ν˜•νƒœλ‘œ 반볡문처럼 돌리게 λœλ‹€. μ•„λ‹ˆλ©΄ while Trueλ₯Ό 써도 될 것 κ°™λ‹€.

def BinarySearch(arr, val, low, high):
    if low > high:
        return False
    
    mid = (low + high) // 2
    if arr[mid] > val:
        return BinarySearch(arr, val, low, mid - 1)
    elif arr[mid] < val:
        return BinarySearch(arr, val, mid + 1, high)
    else:
        return True

N = int(input())
A = list(map(int, input().split()))
M = int(input())
M_list = list(map(int, input().split()))
A = sorted(A)     

for m in M_list:
    if BinarySearch(A, m, 0, N-1):
        print(1)
    else:
        print(0)

μ‹œκ°„λ³΅μž‘λ„

맀 μ‹œν–‰λ§ˆλ‹€ 검색할 자료의 μˆ˜κ°€ 1/2μ”© μ€„μ–΄λ“ λ‹€λŠ” νŠΉμ§•μ΄ μžˆλ‹€. 자료의 개수 Nμ—μ„œ 계속 1/2을 κ³±ν•˜λŠ” ν˜•μ‹μ„ ν•˜λ‹€λ³΄λ©΄ μ΅œμ’…μ μœΌλ‘œ kλ²ˆν–ˆμ„ λ•Œ μ•„λž˜μ™€ 같이 남은 자료의 μˆ˜κ°€ 1이 λ˜λŠ” 식이 λ‚˜μ˜¨λ‹€.

이 λ•Œ μš°λ¦¬κ°€ ꡬ해야 ν•˜λŠ” 것은 k값이기 λ•Œλ¬Έμ—, 양변에 2의 kμŠΉμ„ κ³±ν•˜κ³  둜그λ₯Ό μ·¨ν•΄μ£Όλ©΄ λ‹€μŒκ³Ό 같이 kλŠ” log2N이 λœλ‹€.

결과적으둜 자료 Nκ°œμ— λŒ€ν•œ 이진 νƒμƒ‰μ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” BigO ν‘œκΈ°λ²•μœΌλ‘œ λ‹€μŒκ³Ό κ°™λ‹€. Big O ν‘œκΈ°λ²•μ—μ„œ μƒμˆ˜λŠ” λ¬΄μ‹œν•˜κΈ° λ•Œλ¬Έμ— 2λŠ” μ œμ™Έν•˜κ³  log만 μ“°μ—¬μ‘Œλ‹€)

- Big Oν‘œκΈ°λ²•

μœ„ν‚€λ°±κ³Όμ—λŠ” λ„ˆλ¬΄ μ–΄λ ΅κ²Œ μ¨μ Έμžˆμ–΄μ„œ 링크λ₯Ό μ°Έκ³ ν–ˆλ‹€. λ‹€λ₯Έ 말둜 점근 ν‘œκΈ°λ²•μ΄λΌκ³ λ„ ν•œλ‹€.

"μ‹€ν–‰ μ‹œκ°„μ€ μ΅œλŒ€ν•œ 이만큼 μ»€μ§€μ§€λ§Œ 더 천천히 컀질 μˆ˜λ„ μžˆλ‹€"λŠ” 의미인 점근적 ν‘œκΈ°λ²• ν˜•νƒœλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 νŽΈλ¦¬ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이런 경우λ₯Ό μœ„ν•΄ "big-O" ν‘œκΈ°λ²•μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.

big-OλŠ” μ•Œκ³ λ¦¬μ¦˜μ˜ νš¨μœ¨μ„±μ„ λ‚˜νƒ€λ‚΄λŠ” μ§€ν‘œμž…λ‹ˆλ‹€. big-Oλ₯Ό μ΄μš©ν•˜μ—¬ λ‚΄κ°€ κ°œμ„ ν•œ μ•Œκ³ λ¦¬μ¦˜μ΄ λΉ¨λΌμ‘ŒλŠ”μ§€, λ©”λͺ¨λ¦¬λ₯Ό 많이 μž‘μ•„ λ¨Ήμ§€λŠ” μ•ŠλŠ”μ§€ λ“±μ˜ μ•Œκ³ λ¦¬μ¦˜μ˜ μ„±λŠ₯을 νŒλ‹¨ν•©λ‹ˆλ‹€. μ‹œκ°„μ— λŒ€ν•œ κ°œλ…μΈ μ‹œκ°„ λ³΅μž‘λ„μ™€ 곡간에 λŒ€ν•œ 곡간 λ³΅μž‘λ„κ°€ μžˆμŠ΅λ‹ˆλ‹€. (μ°Έκ³ : 링크)

κ·Έλ‚˜λ§ˆ μ‰½κ²Œ μ„€λͺ…λ˜μ–΄ μžˆλŠ” 링크λ₯Ό 가져와봀닀.

μ‹œκ°„λ³΅μž‘λ„ 비ꡐ

κ²½μš°μ— λ”°λΌμ„œ μ •ν™•ν•œ μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ΅¬ν•˜λŠ” 게 μ–΄λ €μšΈ 수 μžˆλ‹€. 이에 κ°€μž₯ μ°¨μˆ˜κ°€ 높은 κ²ƒλ§Œ 남겨놓아 λΉ„κ΅ν•˜λŠ” λΉ…μ˜€ ν‘œκΈ°λ²•μ΄λ‹€. μ°¨μˆ˜κ°€ 높은 n이 μ²˜λ¦¬ν•  데이터가 λ§Žμ„μˆ˜λ‘ κ·Έ 차이가 크기 λ•Œλ¬Έμ΄λ‹€.

T(n)=n5+n3+n+5 => O(n)=n5

λΉ…μ˜€ ν‘œκΈ°λ²•μ€ 식을 λ‹¨μˆœν™”ν•˜λŠ” 것보닀 "μ•Œκ³ λ¦¬μ¦˜μ„ μˆ˜ν–‰μ‹œκ°„μ— λ”°λ₯Έ μ„±λŠ₯ 기쀀을 λ‚˜λˆ„κΈ° 쉽닀"에 μ˜λ―Έκ°€ μžˆλ‹€. μ •ν™•ν•œ 식을 λͺ¨λ₯΄λ”라도 "이 μ•Œκ³ λ¦¬μ¦˜μ˜ μ„±λŠ₯은 μ—¬κΈ° 정도닀"라고 νŒλ‹¨ν•  수 있기 λ•Œλ¬Έμ΄λ‹€. λ‹€μŒμ€ κΈ°μ€€μœΌλ‘œ 자주 μ‚¬μš©λ˜λŠ” λΉ…μ˜€ ν‘œκΈ°λ‹€.

  • O(1) : μƒμˆ˜μ‹œκ°„(Constant Time)
  • O(logn) : λ‘œκ·Έμ‹œκ°„ λ˜λŠ” λŒ€μˆ˜μ‹œκ°„(Logarithmic)
  • O(n) : μ„ ν˜•μ‹œκ°„(Linear)
  • O(nlogn) : λ‘œκ·Έμ„ ν˜•μ‹œκ°„(Log-Linear)
  • O(n2) : μ œκ³±μ‹œκ°„(Quadratic)
  • O(n3) : μ„Έμ œκ³±μ‹œκ°„(Cubic)
  • O(2n) : μ§€μˆ˜μ‹œκ°„(Exponential)
    ** λ§ˆν¬λ‹€μš΄μ—μ„œ 제곱 ν‘œμ‹œκ°€ μ•ˆ λ˜μ–΄μ„œ n2, n3, 2n으둜 ν‘œμ‹œν–ˆμœΌλ‚˜ μ‹€μ œλ‘œλŠ” 제곱 ν‘œμ‹œλ˜μ–΄μ•Όλ¨!

직접 κ·Έλž˜ν”„λŠ” https://www.desmos.com/calculator μ—μ„œ κ·Έλ €λ³Ό 수 μžˆλ‹€. 2n을 μ œμ™Έν•˜λ©΄ μ΄ˆλ°˜λΆ€μ— O(1)보닀 더 쒋은 μ„±λŠ₯처럼 κ·Έλž˜ν”„μ— λ‚˜μ˜€μ§€λ§Œ, μ‹€μ œλ‘œ 데이터 μ²˜λ¦¬λŠ” κ°œμˆ˜κ°€ 1λΆ€ν„° μ‹œμž‘μ΄λ―€λ‘œ μ˜λ―Έκ°€ μ—†λ‹€.

logn의 μ„±λŠ₯이 ꡉμž₯히 쒋은 것을 μ•Œ 수 μžˆλŠ”λ° 이게 λ°”λ‘œ 이진 탐색!

profile
이사간 λΈ”λ‘œκ·Έ: yenilee.github.io

0개의 λŒ“κΈ€