3장 알고리즘의 효율
이번 강의에서 배울 것
- 순차 탐색·이진 탐색·선택 정렬·패턴 매칭의 최선/최악/평균 Θ를 말할 수 있다.
- shuffle-left, copy-over, converging-pointers를 표로 추적하고 정확한 복사 횟수를 셀 수 있다.
- 이진 탐색 트리를 그리고 최악 비교 횟수와 그 예를 찾을 수 있다.
3장 알고리즘의 효율
학습 흐름
좋은 알고리즘의 조건: correctness · ease of understanding · elegance · efficiency
↓
일의 단위(unit of work)를 정하고 센다 → order of magnitude Θ(…)
↓
Θ(n): 순차 탐색 · copy-over · converging-pointers Θ(lg n): 이진 탐색
Θ(n²): 선택 정렬 · shuffle-left(최악) Θ(m×n): 패턴 매칭(최악)
↓
Θ(2ⁿ): 해밀턴 회로 brute force → intractable → approximation1. 좋은 알고리즘의 조건
| 속성 | 뜻 |
|---|---|
| Correctness | 기본 전제. 모든 입력에 올바른 결과 |
| Ease of understanding (clarity) | program maintenance(오류 수정, 새 요구사항 반영)를 쉽게 함 |
| Elegance | 알고리즘의 "스타일". 예: 1부터 100까지 합을 루프 대신 가우스 공식 100·101/2 = 5050으로 |
| Efficiency | 자원(시간·공간)을 신중하게 쓰는 정도 |
가우스 방식(elegance)으로 2 + 4 + 6 + … + 100 과 2 + 4 + … + 2n 을 구하시오.
정답 확인
2 + 4 + … + 2n = 2(1 + 2 + … + n) = 2 · n(n + 1)/2 = n(n + 1)
n = 50이면 50 · 51 = 2550
2. 순차 탐색과 Θ(n)
일의 단위: NAME과 목록 이름의 비교 횟수
| Best case | Worst case | Average case |
|---|---|---|
| 1 (맨 앞) | n (맨 끝 또는 없음) | 약 n/2 |
3. 선택 정렬과 Θ(n²)
1 Get values for n and the n list items
2 Set the marker for the unsorted section at the end of the list
3 While the unsorted section is not empty, do steps 4–6
4 Select the largest number in the unsorted section ← Find Largest
5 Exchange it with the last number in the unsorted section
6 Move the marker left one position
7 Stop| n | n² | 비교 횟수 n(n − 1)/2 |
|---|---|---|
| 10 | 100 | 45 |
| 100 | 10,000 | 4,950 |
| 1,000 | 1,000,000 | 499,500 |
두 값 바꾸기 (Figure 3.8, 3.9)
틀린 방법 맞는 방법
X ← Y (X=5, Y=5) T ← X (T=3)
Y ← X (X=5, Y=5) ✗ X ← Y (X=5)
Y ← T (Y=3) ✓Θ(n²)과 Θ(n)의 비교
| n | 알고리즘 A: 0.0001n² | 알고리즘 B: 100n |
|---|---|---|
| 1,000 | 100 | 100,000 |
| 100,000 | 1,000,000 | 10,000,000 |
| 1,000,000 | 100,000,000 | 100,000,000 |
| 10,000,000 | 10,000,000,000 | 1,000,000,000 |
같은 일을 하는 알고리즘 A는 0.003n², B는 243n 개의 명령을 실행한다. n이 얼마보다 크면 B가 더 효율적인가?
정답 확인
0.003n² > 243n ⟺ n > 243 / 0.003 = 81,000
n = 100에서 10초 걸리는 알고리즘이 n = 500에서 몇 초 걸릴까? (1) Θ(n)일 때 (2) Θ(n²)일 때
정답 확인
n이 5배 → (1) Θ(n): 5배 = 50초, (2) Θ(n²): 5² = 25배 = 250초
4. 데이터 정리 (Data Cleanup) — 족보 최다 출제
0은 "빈 칸(측정 실패)"입니다. 0을 지우고 유효한 값(legit)만 앞에 모읍니다. 일의 단위는 검사(examination)와 복사(copy) 이고, 시험은 복사 횟수를 묻습니다.
4-1. Shuffle-left (Figure 3.14)
1 Get values for n and the n data items
2 Set legit to n
3 Set left to 1
4 Set right to 2
5 While left ≤ legit do steps 6–14
6 If the item at left is not 0 then
7 Increase left by 1
8 Increase right by 1
9 Else (the item at left is 0)
10 Reduce legit by 1
11 While right ≤ n do steps 12–13
12 Copy the item at right into position (right − 1)
13 Increase right by 1
14 Set right to (left + 1)
15 Stop| 경우 | 언제 | 복사 | Θ |
|---|---|---|---|
| Best | 0이 하나도 없음 | 0 (검사 n번) | Θ(n) |
| Worst | 모두 0 | 0마다 n − 1개씩, n번 → n(n − 1) | Θ(n²) |
| 공간 | n, legit, left, right 4칸만 추가 | 공간 효율적 |
0 0 0 0 0 0 (n = 6)에 shuffle-left를 실행하면 복사가 정확히 몇 번인가?
정답 확인
left는 계속 1에 머물고, 0을 만날 때마다 2..6의 5개를 복사한다. legit이 6 → 0이 될 때까지 6번 반복하므로 6 × 5 = 30 = n(n − 1).
4-2. Copy-over (Figure 3.15)
1 Get values for n and the n data items
2 Set left to 1
3 Set newposition to 1
4 While left ≤ n do steps 5–9
5 If the item at left is not 0 then
6 Copy the item at left into position newposition in the new list
7 Increase left by 1
8 Increase newposition by 1
9 Else increase left by 1
10 Stop[3 0 0 2 6 7 0 0 5 1] → 새 리스트 3 2 6 7 5 1, 복사 6번(0이 아닌 원소 수), 순서 유지.
4-3. Converging-pointers (Figure 3.16)
1 Get values for n and the n data items
2 Set legit to n
3 Set left to 1
4 Set right to n
5 While left < right do steps 6–10
6 If the item at left is not 0 then increase left by 1
7 Else (the item at left is 0) do steps 8–10
8 Reduce legit by 1
9 Copy the item at right into position left
10 Reduce right by 1
11 If the item at left is 0, then reduce legit by 1
12 Stop4-4. 세 알고리즘 비교 (Figure 3.17)
| Shuffle-left 시간 | 공간 | Copy-over 시간 | 공간 | Converging 시간 | 공간 | |
|---|---|---|---|---|---|---|
| Best | Θ(n) | n | Θ(n) | n | Θ(n) | n |
| Worst | Θ(n²) | n | Θ(n) | 2n | Θ(n) | n |
| Average | Θ(n²) | n | Θ(n) | n ≤ x ≤ 2n | Θ(n) | n |
| 순서 유지 | O | O | X |
다음 리스트에 세 알고리즘을 각각 적용한 결과와 복사 횟수를 쓰시오. (index는 1부터)
[0, 7, 0, 3, 5, 0]
힌트 1 보기
Shuffle-left: 첫 칸이 0이면 left는 1에 머문 채로 5개를 당깁니다.
정답 확인
| 알고리즘 | 결과 | 복사 횟수 |
|---|---|---|
| Shuffle-left | 7 3 5 | 5 + 4 + 2 = 11 |
| Copy-over | 7 3 5 | 3 |
| Converging-pointers | 5 7 3 | 3 |
Converging-pointers 추적: A[1] = 0 ← A[6] = 0 (right 5), 여전히 0 → A[1] ← A[5] = 5 (right 4), 5·7 통과 후 A[3] = 0 ← A[4] = 3 (right 3), left = right = 3, A[3] = 3 ≠ 0 → legit = 3.
5. 이진 탐색 (Binary Search)과 Θ(lg n)
정렬된 목록에서만 쓸 수 있습니다. 가운데와 비교해 절반을 버립니다.
1 Get values for NAME, n, N₁…Nₙ and T₁…Tₙ
2 Set beginning to 1 and set Found to NO
3 Set end to n
4 While Found = NO and beginning ≤ end do steps 5–10
5 Set m to the middle value between beginning and end
6 If NAME = Nₘ then
7 Print Tₘ
8 Set Found to YES
9 Else if NAME precedes Nₘ alphabetically, set end = m − 1
10 Else set beginning = m + 1
11 If (Found = NO) print 'I am sorry but that name is not in the directory'
12 Stop가운데 m = ⌊(beginning + end) / 2⌋ (나머지 버림)로 계산합니다.
| n | 8 | 16 | 32 | 64 | 128 | 1,000 | 1,000,000 |
|---|---|---|---|---|---|---|---|
| lg n | 3 | 4 | 5 | 6 | 7 | ≈ 10 | ≈ 20 |
족보 유형: 이진 탐색 트리 그리기 (Sample Q6)
Arturo(1), Elsa(2), JoAnn(3), John(4), Jose(5), Lee(6), Snyder(7), Tracy(8)
John (4) ← 1번째 비교: ⌊(1+8)/2⌋ = 4
/ \
Elsa (2) Lee (6) ← 2번째: ⌊(1+3)/2⌋ = 2, ⌊(5+8)/2⌋ = 6
/ \ / \
Arturo (1) JoAnn (3) Jose (5) Snyder (7) ← 3번째: ⌊(7+8)/2⌋ = 7
\
Tracy (8) ← 4번째3, 6, 7, 9, 12, 14, 18, 21, 22, 31, 43 에서 이진 탐색으로 35를 찾을 때 비교하는 수를 순서대로 쓰시오.
정답 확인
14 → 22 → 31 → 43, 그다음 beginning(11) > end(10)이 되어 "없음".
(1..11) m = 6 → 14 < 35 → (7..11) m = 9 → 22 → (10..11) m = 10 → 31 → (11..11) m = 11 → 43 > 35 → end = 10
7개 원소의 이진 탐색 트리(Figure 3.19)에서 각 원소를 찾는 비교 횟수의 평균과 최악을 구하시오.
정답 확인
4는 1번, 2·6은 2번, 1·3·5·7은 3번 → 합 1 + 4 + 12 = 17, 평균 17/7 ≈ 2.43, 최악 3. 평균이 최악과 거의 같다(원소의 절반이 맨 아래 층에 있기 때문).
6. 패턴 매칭의 효율
일의 단위: 패턴 문자와 텍스트 문자의 비교
| 경우 | 예 | 비교 횟수 | Θ |
|---|---|---|---|
| Best | 매 시작 위치에서 첫 글자부터 불일치 (text = ABCDEFGH, pattern = XYZ) | n − m + 1 | Θ(n) |
| Worst | 매번 마지막 글자에서 불일치 (text = AAAAAAAA, pattern = AAB) | (n − m + 1) × m | Θ(m × n) |
보통 m ≪ n이므로 실제로는 거의 Θ(n)입니다.
7. 감당할 수 없을 때 (When Things Get Out of Hand)
| 용어 | 뜻 |
|---|---|
| Polynomially bounded | 일의 양이 n²(더 일반적으로 n의 다항식)의 상수배를 넘지 않음 |
| Graph | 노드(node)와 이를 잇는 간선(edge)의 모음 |
| Hamiltonian circuit | 한 노드에서 출발해 다른 모든 노드를 정확히 한 번씩 지나 출발점으로 돌아오는 경로 |
| Exponential algorithm | Θ(2ⁿ). 입력이 하나 늘 때마다 일이 두 배 |
| Brute force | 모든 가능성을 다 시도해 "문제를 두들겨 패서" 푸는 방법 |
| Intractable problem | 다항식 시간 알고리즘이 존재하지 않는 문제 |
| Approximation algorithm | 정확한 해 대신 가까운 해를 빠르게 구함 (예: bin packing에서 first-fit) |
n = 10, 20, 50일 때 lg n, n lg n, n² 표를 채우시오 (lg 10 ≈ 3.32). (중간 족보 문제 10)
힌트 1 보기
lg 20 = lg 10 + 1, lg 50 = lg 100 − 1 = 2·lg 10 − 1
정답 확인
| n | lg n | n lg n | n² |
|---|---|---|---|
| 10 | 3.3 | 33.2 | 100 |
| 20 | 4.3 | 86.4 | 400 |
| 50 | 5.6 | 282.2 | 2,500 |
n이 5배일 때 n lg n은 약 8.5배, n²은 25배 늘어난다.
100n² 명령을 실행하는 알고리즘이 0.01·2ⁿ 명령을 실행하는 알고리즘보다 효율적이 되는 n은 대략 얼마인가?
정답 확인
n = 22: 100 · 484 = 48,400 > 0.01 · 4,194,304 ≈ 41,943
n = 23: 100 · 529 = 52,900 < 0.01 · 8,388,608 ≈ 83,886
따라서 n ≥ 23부터 Θ(n²) 쪽이 더 효율적이다. 지수 알고리즘의 작은 상수(0.01)도 금방 따라잡힌다.
효율 요약 (Figure 3.22)
| 문제 | 일의 단위 | 알고리즘 | Best | Worst | Average |
|---|---|---|---|---|---|
| Searching | 비교 | Sequential search | 1 | Θ(n) | Θ(n) |
| Binary search | 1 | Θ(lg n) | Θ(lg n) | ||
| Sorting | 비교·교환 | Selection sort | Θ(n²) | Θ(n²) | Θ(n²) |
| Data cleanup | 검사·복사 | Shuffle-left | Θ(n) | Θ(n²) | Θ(n²) |
| Copy-over | Θ(n) | Θ(n) | Θ(n) | ||
| Converging-pointers | Θ(n) | Θ(n) | Θ(n) | ||
| Pattern matching | 문자 비교 | Forward march | Θ(n) | Θ(m × n) |
8. 족보·교재 연습
342명이 참가하는 테니스 토너먼트(한 경기 2명, 진 사람 탈락)에서 우승자를 정하려면 몇 경기가 필요한가? 라운드별 계산으로 구하고, 더 우아한 방법도 쓰시오. (Sample Q7)
정답 확인
| 라운드 | 남은 인원 | 경기 수 | 부전승 |
|---|---|---|---|
| 1 | 342 | 171 | 0 |
| 2 | 171 | 85 | 1 |
| 3 | 86 | 43 | 0 |
| 4 | 43 | 21 | 1 |
| 5 | 22 | 11 | 0 |
| 6 | 11 | 5 | 1 |
| 7 | 6 | 3 | 0 |
| 8 | 3 | 1 | 1 |
| 9 | 2 | 1 | 0 |
합계 171 + 85 + 43 + 21 + 11 + 5 + 3 + 1 + 1 = 341경기
우아한 방법: 경기마다 정확히 1명이 탈락하고 우승자 1명만 남으므로 경기 수 = 탈락자 수 = 342 − 1 = 341. 계산이 필요 없어 더 명확(clarity)하고 우아(elegance)하며 효율적이다.
다음 T/F를 판정하시오.
(1) 순차 탐색을 무작위 입력으로 여러 번 돌리면 평균 비교 횟수는 대략 n/2이다.
(2) 같은 일을 하는 Θ(n²)와 Θ(n) 알고리즘이 있으면, n이 충분히 클 때 Θ(n²) 쪽이 상수와 관계없이 더 많은 일을 한다.
(3) Shuffle-left의 최악 경우는 Θ(n²)이다.
(4) 이진 탐색은 정렬되지 않은 목록에도 쓸 수 있다.
(5) Copy-over의 최악 경우는 리스트가 모두 0일 때이다.
정답 확인
(1) T (정확히는 (n+1)/2) (2) T (3) T (모두 0일 때) (4) F (5) F — 모두 0이면 copy-over의 최선(복사 0, 추가 공간 0). 최악은 0이 하나도 없을 때.
다음 알고리즘에서 n = 4, n = 8일 때 출력되는 값을 쓰고, 출력 횟수의 Θ를 구하시오. n = 16이면 몇 번 출력하는가?
Get value for n
Set k to 1
While k ≤ n do
Set j to n / 2
While j ≥ 1 do
Print j
Set j to j / 2
End of loop
Increase k by 1
End of loop정답 확인
- n = 4:
2 1을 4번 → 2 1 2 1 2 1 2 1 - n = 8:
4 2 1을 8번 - 안쪽 루프는 j를 반씩 줄이므로 lg n번, 바깥은 n번 → Θ(n lg n)
- n = 16: 안쪽 8, 4, 2, 1 = 4번 × 16 = 64번
리스트에서 두 번째로 큰 값을 찾는 두 방법의 차수를 비교하시오. (a) 선택 정렬 후 뒤에서 두 번째를 꺼냄 (b) Find Largest를 두 번 실행(첫 번째 최댓값을 지우고 다시)
정답 확인
(a) 선택 정렬 Θ(n²) (b) Find Largest는 Θ(n)이고 두 번 해도 2·Θ(n) = Θ(n). 정렬은 필요한 것보다 훨씬 많은 일을 한다.
전화국이 n개 구역 사이의 통화량을 n × n 표로 관리한다. (a) 표를 한 번 출력할 때 출력 명령 수 (b) 구역장 n명에게 한 부씩 n부 출력할 때 출력 명령 수와 Θ를 구하시오.
정답 확인
(a) 이중 반복으로 n²개 → Θ(n²) (b) 그것을 n번 → n³, Θ(n³)
9. 맨해튼 거리 (슬라이드 마지막)
격자 도로에서 (x₁, y₁)에서 (x₂, y₂)로 가는 최단 경로의 길이는 경로 모양과 관계없이 |x₁ − x₂| + |y₁ − y₂| 입니다(빨강·파랑·노랑 경로 모두 같은 길이, 초록 직선만 짧음). 모든 경로를 나열(brute force)하지 않고 공식 하나로 끝내는 것이 elegance의 예입니다.
정리 카드
좋은 알고리즘의 네 가지 속성은?
correctness, ease of understanding(clarity), elegance, efficiency.
선택 정렬의 비교 횟수와 Θ는?
n(n − 1)/2, 모든 경우 Θ(n²). 교환은 n번.
shuffle-left / copy-over / converging-pointers의 최악 시간·공간은?
Θ(n²)·n / Θ(n)·2n / Θ(n)·n. converging-pointers만 순서가 바뀐다.
shuffle-left가 n개의 0에 대해 하는 복사 횟수는?
n(n − 1). 0마다 n − 1개를 당기고 그것을 n번 반복한다.
이진 탐색의 전제조건과 최악 비교 횟수는?
목록이 정렬되어 있어야 한다. 최악 ⌊lg n⌋ + 1번, Θ(lg n).
intractable problem과 대처 방법은?
다항식 시간 알고리즘이 없는 문제(예: 해밀턴 회로). brute force는 Θ(2ⁿ)이라 approximation algorithm을 쓴다.
내용을 이해했다면 학습 완료를 체크해 주세요.