전화번호부에서 친구 이름 찾기, 도서관에서 책 찾기, 마트에서 원하는 과자 찾기... 이 모든 것이 "검색"입니다!
데이터가 적으면 하나씩 찾아도 금방이지만, 데이터가 많아지면 찾는 방법이 매우 중요해집니다.
알파벳 순서가 없으면 단어 찾는 데 오래 걸림
알파벳 순서대로라면 빠르고 쉽게 찾을 수 있음
방법 1: 방 구석구석을 처음부터 끝까지 하나씩 뒤진다 → 순차 검색
방법 2: "보통 소파 근처에 있으니까" 하고 범위를 좁혀 찾는다 → 이진 검색처럼 범위를 줄이는 방법
방법 3: 리모컨 보관함을 만들어서 항상 같은 곳에 둔다 → 인덱스(색인) 방식
Finding a friend's name in contacts, looking for a book in a library, searching for snacks at a store... These are all "searching"!
With little data, checking one-by-one is fast. But as data grows, the method of searching becomes critical.
Without alphabetical order, finding words takes a long time
With alphabetical order, you find words quickly and easily
Method 1: Search every corner of the room one by one → Sequential Search
Method 2: "It's usually near the sofa" — narrow down the area → Like Binary Search
Method 3: Use a remote holder so it's always in the same place → Index approach
| 알고리즘 | 정렬 필요? | 속도 | 난이도 |
|---|---|---|---|
| 순차 검색 | 필요 없음 | 느림 O(n) | 매우 쉬움 |
| 이진 검색 | 필요함 | 빠름 O(log n) | 보통 |
| 트리 검색 | 트리 구조 | 빠름 O(log n) | 어려움 |
| Algorithm | Sorted? | Speed | Difficulty |
|---|---|---|---|
| Sequential | Not needed | Slow O(n) | Very Easy |
| Binary | Required | Fast O(log n) | Medium |
| Tree | Tree structure | Fast O(log n) | Hard |
선생님이 출석부에서 "김철수"를 찾으려면, 1번부터 차례대로 이름을 확인합니다. "아, 15번에 있네!" — 이것이 순차 검색입니다.
- 이해하기 가장 쉬운 검색 방법
- 데이터가 정렬되어 있지 않아도 사용 가능
- 구현이 매우 간단
- 데이터가 많으면 매우 느림
- 최악의 경우 모든 데이터를 다 확인해야 함
- 데이터 100만 개면 최대 100만 번 비교!
| 경우 | 비교 횟수 | 설명 |
|---|---|---|
| 최선 (Best) | 1번 | 첫 번째에서 바로 발견 |
| 평균 (Average) | n/2번 | 중간쯤에서 발견 |
| 최악 (Worst) | n번 | 마지막에 있거나 없음 |
A teacher looking for "Kim Cheolsu" checks names starting from #1 in order. "Found at #15!" — this is Sequential Search.
- Easiest search method to understand
- Works even on unsorted data
- Very simple to implement
- Very slow with large data
- Worst case: must check every element
- 1 million items = up to 1 million comparisons!
| Case | Comparisons | Description |
|---|---|---|
| Best | 1 | Found at the first position |
| Average | n/2 | Found around the middle |
| Worst | n | At the end or not found |
배열 [188, 150, 168, 162, 105, 120, 177, 50]에서 162를 찾는 과정:
Find 162 in [188, 150, 168, 162, 105, 120, 177, 50]:
배열 [188, 150, 168, 162, 105, 120, 177, 50]에서 999를 찾는 과정:
Find 999 in [188, 150, 168, 162, 105, 120, 177, 50]:
가장 기본적인 순차 검색 코드입니다. 한 줄씩 이해해 봅시다!
pos = -1 → 처음에는 "못 찾음" 상태로 시작for i in range(size) → 0번부터 끝까지 반복if ary[i] == fData → 현재 값이 찾는 값인지 비교break → 찾았으면 더 이상 반복할 필요 없이 즉시 종료!The most basic sequential search code. Let's understand it line by line!
pos = -1 → Start with "not found" statefor i in range(size) → Loop from index 0 to endif ary[i] == fData → Compare current value with targetbreak → Once found, stop immediately!영어 사전에서 "cat"을 찾다가 "dog"이 나왔다면? 이미 지나쳤으니 더 볼 필요 없습니다! 사전은 정렬되어 있으니까요.
정렬된 배열 [50, 105, 120, 150, 162, 168, 177, 188]에서 100을 찾는 과정:
Looking for "cat" in a dictionary, if you see "dog" — you've passed it! No need to keep looking! The dictionary is sorted.
Find 100 in sorted [50, 105, 120, 150, 162, 168, 177, 188]:
| 항목 | 비정렬 순차 검색 | 정렬 순차 검색 |
|---|---|---|
| 데이터 정렬 | 필요 없음 | 반드시 필요 |
| 검색 성공 시 | 같음 | 같음 |
| 검색 실패 시 | 끝까지 비교 (느림) | 중간에 중단 가능 (빠름) |
| 시간 복잡도 | O(n) | O(n) (but 평균 빠름) |
| 코드 추가 | 기본 코드 | elif + sort() 추가 |
배열 [188, 50, 150, 168, 50, 162, 105, 120, 177, 50]에서 50이 있는 모든 위치를 리스트로 반환하는 순차 검색 함수를 작성하세요.
힌트: break를 없애고, 결과를 리스트에 append하세요!
| Item | Unsorted Sequential | Sorted Sequential |
|---|---|---|
| Sorting needed? | No | Yes, required |
| When found | Same | Same |
| When not found | Check all (slow) | Stop early (faster) |
| Time Complexity | O(n) | O(n) (but avg. faster) |
| Code change | Basic code | Add elif + sort() |
In [188, 50, 150, 168, 50, 162, 105, 120, 177, 50], write a sequential search that returns all positions of 50 as a list.
Hint: Remove break, and append results to a list!
"1~100 사이의 숫자를 맞춰보세요!"
"50!" → "더 크다!" → "75!" → "더 작다!" → "62!" → "정답!"
매번 범위가 절반으로 줄어듭니다. 이것이 바로 이진 검색의 원리입니다!
| 데이터 수 | 순차 검색 (최대) | 이진 검색 (최대) |
|---|---|---|
| 10개 | 10번 | 4번 |
| 1,000개 | 1,000번 | 10번 |
| 1,000,000개 | 1,000,000번 | 20번 |
| 10억 개 | 10억 번 | 30번 |
"Guess a number between 1 and 100!"
"50!" → "Higher!" → "75!" → "Lower!" → "62!" → "Correct!"
The range halves every time. This is exactly how Binary Search works!
| Data Size | Sequential (max) | Binary (max) |
|---|---|---|
| 10 | 10 | 4 |
| 1,000 | 1,000 | 10 |
| 1,000,000 | 1,000,000 | 20 |
| 1 Billion | 1 Billion | 30 |
정렬된 배열 [50, 60, 105, 120, 150, 160, 162, 168, 177, 188]에서 162를 찾아봅시다!
Find 162 in sorted [50, 60, 105, 120, 150, 160, 162, 168, 177, 188]:
Binary search repeatedly divides the search range in half and conquers by choosing which half to keep.
Each step eliminates 50% of remaining data — that's why it's so fast!
배열 [50, 60, 105, 120, 150]에서 80을 찾는 과정:
Find 80 in [50, 60, 105, 120, 150]:
mid = (start + end) // 2//는 나눗셈 후 소수점 버림(정수 나눗셈)입니다.start = mid + 1end = mid - 1mid + 1과 mid - 1에서 +1, -1을 빠뜨리면 무한 루프에 빠질 수 있습니다!
mid = (start + end) // 2// is integer division (drops decimal).start = mid + 1end = mid - 1mid + 1 and mid - 1 can cause an infinite loop!
start = 0, end = len(array) - 1start <= end:mid = (start + end) // 2target == ary[mid] → Return mid (found!)target > ary[mid] → start = mid + 1 (go right)target < ary[mid] → end = mid - 1 (go left)log₂(n) means "how many times can you divide n by 2?"
log₂(8) = 3 → divide 8 in half 3 times to get 1
log₂(1024) = 10 → divide 1024 in half 10 times
log₂(1,000,000) ≈ 20 → only 20 steps for a million items!
10만 개의 랜덤 데이터를 정렬한 후, 이진 검색으로 특정 값을 찾을 때 비교 횟수를 출력하세요.
힌트: 전역 변수 count를 사용하여 while 루프 안에서 매번 1씩 증가시키세요!
100만 개의 랜덤 데이터에서 같은 값을 순차 검색과 이진 검색으로 찾아보고, 각각 몇 번 비교했는지 출력하세요.
힌트: 순차 검색은 비정렬 배열, 이진 검색은 정렬 배열을 사용하세요!
Sort 100,000 random numbers, then binary search for a value and print the number of comparisons.
Hint: Use a global variable count, increment by 1 each loop iteration!
With 1 million random items, search for the same value using both sequential and binary search. Print the comparison count for each.
Hint: Use unsorted array for sequential, sorted for binary!
교과서 뒤에 있는 "찾아보기"(색인)를 생각해보세요. "배열 → 45페이지, 스택 → 120페이지" 같은 것이죠.
책 전체를 뒤지지 않고도 원하는 주제의 페이지를 바로 찾을 수 있습니다!
도서관 책장에 책이 꽂혀 있다고 합시다:
['어린왕자', '이방인', '부활', '신곡', '돈키호테', '동물농장', '데미안', '파우스트', '대지']
이 순서로는 빠른 검색이 불가능합니다. 하지만 도서명 색인표를 만들면:
['대지→8', '데미안→6', '돈키호테→4', '동물농장→5', '부활→2', '신곡→3', '어린왕자→0', '이방인→1', '파우스트→7']
정렬된 색인표에서 이진 검색을 할 수 있습니다!
Think of the "Index" at the back of a textbook. "Array → p.45, Stack → p.120"
You can find the page of any topic instantly without flipping through the whole book!
Imagine books on a shelf:
['Little Prince', 'Stranger', 'Resurrection', 'Inferno', 'Don Quixote', ...]
In this order, fast search is impossible. But with a Title Index:
['Don Quixote→4', 'Inferno→3', 'Little Prince→0', ...]
Now we can use binary search on the sorted index!
책장 데이터에서 색인을 만들고 이진 검색으로 찾는 예제입니다.
ary[mid][1]로 원본 위치를 반환Create an index from bookshelf data and use binary search.
ary[mid][1] (the original position)(data[pos], index) creates a tuple. [0] is the search key, [1] is the original position. Tuples are like pairs of information bundled together!
"동물인가요?" → "예" → "다리가 4개인가요?" → "아니오" → "날 수 있나요?" → "예" → "독수리!"
매번 예/아니오로 범위를 좁혀가는 것이 트리 검색과 비슷합니다!
모든 노드에 대해:
- 왼쪽 서브트리의 모든 값 < 현재 노드의 값
- 오른쪽 서브트리의 모든 값 > 현재 노드의 값
"Is it an animal?" → "Yes" → "Does it have 4 legs?" → "No" → "Can it fly?" → "Yes" → "Eagle!"
Narrowing down with yes/no at each step is similar to tree search!
For every node:
- All values in the left subtree < current node's value
- All values in the right subtree > current node's value
| 항목 | 순차 검색 | 이진 검색 | 트리 검색 |
|---|---|---|---|
| 정렬 필요 | 필요 없음 | 필수 | 트리 구조 |
| 시간 복잡도 | O(n) | O(log n) | O(log n) |
| 구현 난이도 | 매우 쉬움 | 쉬움 | 어려움 |
| 데이터 추가/삭제 | 쉬움 | 재정렬 필요 | 복잡 |
| 적합한 상황 | 소량 데이터 | 대량 정적 데이터 | 동적 데이터 |
| 10만 개 최대 비교 | 100,000회 | 17회 | 17회 |
| Item | Sequential | Binary | Tree |
|---|---|---|---|
| Sorting | Not needed | Required | Tree structure |
| Time | O(n) | O(log n) | O(log n) |
| Difficulty | Very Easy | Easy | Hard |
| Insert/Delete | Easy | Need re-sort | Complex |
| Best for | Small data | Large static data | Dynamic data |
| 100K max comp. | 100,000 | 17 | 17 |
Simple but slow. Good for small datasets (<100) or unsorted data.
Fast! Best for large, sorted, rarely changing data.
Good for data that changes frequently (inserts/deletes).
편의점에서 오늘 판매된 물건 목록(중복 포함)에서 각 물건이 몇 개 팔렸는지 세는 프로그램입니다.
random.choice로 판매 목록 20개를 랜덤 생성set()으로 중복 제거 → 판매된 물건 종류 파악del로 제거하며 카운트Count how many of each item was sold today from a sales list (with duplicates).
random.choice generates 20 random sales recordsset() removes duplicates → get unique product listdel when found, count occurrencesToday's sales (20 items):
['삼각김밥', '코카콜라', '바나나맛우유', '삼다수', '삼다수', '코카콜라', ...]
Results:
[('바나나맛우유', 3), ('삼각김밥', 4), ('삼다수', 5), ('코카콜라', 2), ...]
collections.Counter for this task! But this example demonstrates how binary search can be applied to real-world counting problems.
random.choice(list) — randomly picks one item from a list
set(list) — removes all duplicates from a list
del(list[index]) — removes an item at a specific index
- 검색은 데이터 집합에서 원하는 값을 찾는 것
- 순차 검색: 처음부터 끝까지 하나씩 비교 → O(n)
- 정렬된 데이터에서는 더 일찍 중단 가능
- 못 찾으면 -1을 반환 (관례)
- 정렬된 데이터에서 중간값과 비교하여 절반씩 줄여가며 검색 → O(log n)
- 10억 개 데이터도 최대 30번 비교로 검색 가능!
- start, end, mid 세 변수를 사용
- start > end가 되면 검색 실패
- 색인(Index): 비정렬 데이터에 정렬된 검색표를 만듦
- 이진 탐색 트리: 왼쪽 < 부모 < 오른쪽 규칙
- 상황에 따라 적합한 검색 알고리즘 선택이 중요!
- Searching = finding a desired value in a data collection
- Sequential: compare one by one from start → O(n)
- Sorted data allows earlier termination
- Returns -1 when not found (convention)
- Compare with middle, halve range each time → O(log n)
- 1 billion items needs at most 30 comparisons!
- Uses three variables: start, end, mid
- Fails when start > end
- Index: create a sorted lookup table for unsorted data
- BST: left < parent < right rule
- Choosing the right algorithm for the situation matters!
학생 데이터 [['홍길동',85], ['김영희',92], ['박철수',78], ['이미나',95], ['최강',88]]에서 이름으로 검색하여 성적을 출력하는 프로그램을 작성하세요.
조건: 색인(인덱스)을 만들어 이진 검색을 사용하세요!
다음 상황에 가장 적합한 검색 알고리즘은?
① 전화번호부(500만 건)에서 이름으로 검색
② 친구 5명의 생일 목록에서 특정 날짜 검색
③ 쇼핑몰에서 상품이 계속 추가/삭제되는 목록 검색
Given [['Hong',85], ['Kim',92], ['Park',78], ['Lee',95], ['Choi',88]], write a program that searches by name and prints the grade.
Requirement: Use an index with binary search!
Which search algorithm is best for each scenario?
① Search by name in a phone book (5 million entries)
② Search for a date in a list of 5 friends' birthdays
③ Search a shopping mall product list that keeps changing