You are on page 1of 78

알고리즘
3
1 관계 기반 알고리즘

문제와 알고리즘 2
탐색 기반 알고리즘

이 단원에서는 다양한 학문 분야의 복잡한 문제를 해결하기 위해 효율적인 알고리즘을 설


계하고 구현하는 능력을 기른다. 이를 위해 문제와 알고리즘의 특성을 분석하는 방법과 탐색
및 관계 기반의 알고리즘을 설계하는 방법을 학습하고 프로그래밍을 통해 구현한다. 계산의
관점에서 문제와 알고리즘의 효율성을 분석하고, 탐색 및 관계 기반 알고리즘을 적용한 문제
해결을 할 수 있도록 한다.

정보과학-3단원-2차.indd 188 2021-12-20 오전 9:45:35


정보과학-3단원-2차.indd 189 2021-12-20 오전 9:45:36
문제와 알고리즘
컴퓨터는 빠르고 정확한 계산이 가능한 기기이다. 따라서 문제 해결에 컴퓨터를 이용하면 보다 효율적인 해결
이 가능하다.
우리는 매일 ‘정보 검색’이나 ‘길 찾기’ 등의 문제를 컴퓨터 또는 컴퓨팅 시스템(computing system)을 이용하여
해결하고 있다. 또한 컴퓨터를 이용하여 ‘바둑’을 두기도 하고, 다양한 캐릭터들이 상호 작용하는 ‘게임’을 하기도
한다. 이뿐만 아니라 컴퓨터를 이용하여 인간의 ‘유전체 지도를 만들기’도 하고, 인공 지능을 바탕으로 ‘스스로 작
곡하거나 기사를 쓰게 만들기’도 한다.
그렇다면 컴퓨터는 과연 모든 문제를 해결할 수 있을까? 그리고 컴퓨터를 이용하여 문제를 해결하려면 어떻게
해야 할까?

P vs. NP 문제

NP-Hard NP-Hard

NP-Complete vs
P = NP =
NP
NP-Complete
Complexity

P ≠ NP P = NP

지뢰 찾기 문제 해밀턴 경로 문제

190 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 190 2021-12-20 오전 9:45:38


01 문제의 개념과 종류
•계산할 수 있는 문제와 그렇지 않은 문제로 구분할 수 있다.
•문제를 계산의 관점으로 분류할 수 있다.

Think 문제를 분류하는 기준이 있을까?

1 문제의 개념
‘문제’란 해결해야 할 과제, 도전이나 해법이 필요한 어떤 상황, 해답을
요구하는 물음
곤란하고 힘든 일, 성가시고 귀찮은 상황 등을 뜻한다. 문제를 해
논쟁, 논의, 연구
결한다는 것은 어떤 목적이나 목표를 달성하기 위한 해법이나
등의 대상이 되는 것
도움을 만들어 낸다는 것이다.
해결하기 어렵거나
수학을 배워서 수학 문제를 해결하고, 과학을 배워서 과학 난처한 대상 또는 그런 일

문제를 해결하며, 영어를 배우면 외국인과의 의사소통 문제를


귀찮은 일이나 말썽
해결할 수 있다. 따라서 다양한 학문은 일상생활 속에서 만나
어떤 사물과
는 문제를 각 학문의 관점에서 분석하고, 이를 해결하기 위한
관련되는 일
방법을 찾기 위한 이론으로 구성되어 있다고 할 수 있다.
▲▲문제의 사전적 정의
각 학문에서 문제를 바라보는 시각에 조금씩 차이가 있을
수 있다. 그러나 문제를 ‘해결해야 할 대상’으로 보는 것은 동일하다.

•‌인구 문제는 어떻게 해


6÷2(1+2) = ? 결해야 할까?
•‌스키 점프에서 우승하려
면 어떻게 해야 할까?

1 OR 9 •‌미지수 x 를 구하려면
어떻게 해야 할까?

6 / 2(1 + 2)의 결과는 1일까? 9일까? 2(3)을 먼저 강력한 대포는 더 멀리 쏜다. 포탄을 발사해 지구를
계산하면 1이고, 6 ÷ 2를 먼저 계산하면 9이다. 돌게 할 수 있을까?

▲▲수학 문제 ▲▲과학 문제

01
탐구 활동

다음의 주제에 관해 토론하고, 발표해 보자.

❶ 수학 문제와 수학적 문제 해결 방식의 특성은 무엇일까?

1. 문제와 알고리즘 191

정보과학-3단원-2차.indd 191 2021-12-20 오전 9:45:38


수학, 과학에서의 문제 해결 ❷ 과학 문제와 과학적 문제 해결 방식의 특성은 무엇일까?
수학 교과서, 과학 교과서에 담
긴 문제들과 해결 방식을 분석
해 보자.

2 문제의 종류
컴퓨터와 계산 수학, 과학 등과 마찬가지로 정보과학 분야에서는 컴퓨터를 이용하여 효율적으로 문제
컴퓨터는 더 빠르고 정확한 계
산을 위해 만들어진 도구이다.
를 해결하기 위한 방법을 제시한다. 이러한 컴퓨터의 능력은 빠르고 정확한 계산 능력을
바탕으로 한다. 계산 문제(computational problem)란 컴퓨터의 계산 능력(computing
power, computation)을 이용하여 해결 가능한 문제를 뜻한다.
계산 문제 컴퓨터는 한 번에 하나의 작업만 수행할 수 있으며, 대체로 작업의 단위가 매우 작다.
계산 문제는 산술 연산이나 논
리 연산의 조합을 통해 해결 따라서 컴퓨터로 문제를 해결하기 위해서는 여러 가지 작업을 절차적으로 수행해야 한다.
가능한 문제를 말한다.
이러한 관점에서 계산 문제는 절차적으로 해결할 수 있는 모든 문제라고 정의할 수 있다.
다음의 문제는 계산 문제이다.

•12부터 1327까지의 자연수 중에서 소수의 개수는 몇 개인가?

•‌배치가 다음과 같이 주어진 숫자판에서 빈칸으로 다른 숫자들을 이동시켜 완성된 숫자판으


로 만들 수 있는 방법이 존재하는가?

1 2 3 1 2 3
4 5 4 5 6
7 8 6 7 8
주어진 숫자판 완성된 숫자판

•다음 지하철 노선도에서 ‘출발역’에서 ‘도착역’으로 갈 때 최소 환승 횟수를 구하여라.

출발역
도착역

192 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 192 2021-12-20 오전 9:45:39


그러나 세상의 모든 문제들이 계산을 통해 해결되는 것은 아니다. 예를 들어 다음과 같
은 문제들은 계산을 통해 해결이 불가능하다. 따라서 이 문제들은 계산 문제가 아니다.

•현재 지구의 인구는 70억 명을 돌파하였다. 앞으로 10년 후의 인구의 수를 구하여라. 계산할 수 있는 문제와 계산
할 수 없는 문제
10년 후의 인구의 수를 구하
•‌철수는 현재 지하철에 타고 있다. 같은 객차에 타고 있는 사람들 중 키가 작은 사람은 몇 명
기 위해 컴퓨터를 활용할 수는
인지 구하여라. 있으나 정확한 답을 계산해 낼
수는 없다.

•길동이는 마트에서 사과와 배를 샀다. 더 맛있는 과일은 무엇인가?

계산 문제는 그 문제를 해결하는 방법의 특성에 따라 연산 문제를 비롯하여 결정 문제, 계산 가능성 이론


문제의 계산 가능성을 분석하
계수 문제, 최적화 문제 등으로 분류된다. 기 위한 다양한 연구들이 존재
한다.
문제

최적화 문제
최적화 문제란 시간, 거리, 넓
Yes 계산으로 해결 No 이, 부피 또는 이익이 최대 또
할 수 있는가?
는 최소가 되게 하는 점이나
값을 찾는 문제를 말한다.
계산 문제
연산 계수
문제 문제
계산 불가능 문제
결정
문제 최적화
문제

▲▲문제의 분류

먼저 단순한 연산을 통하여 해를 구할 수 있는 문제는 연산 문제라고 한다. 앞서 살펴보


았던 12부터 1327까지의 자연수 중에서 소수의 개수를 구하는 문제가 여기에 해당한다.
결정 문제란 ‘예’ 또는 ‘아니요’로 답할 수 있는 형태의 문제를 뜻한다. 앞서 살펴보았던
숫자 퍼즐 문제가 여기에 해당한다. 또한 여러 가지 답 중에서 가장 적합한 답을 구하는
형태의 문제를 ‘최적화 문제’라고 한다. 출발지부터 목적지까지의 최소 환승 횟수를 구하
는 문제를 사례로 들 수 있다.
계수 문제는 조건에 맞는 경우의 수를 세는 문제로서, ‘최소 환승 횟수’ 문제를 다음과
같이 바꾸면 계수 문제가 된다.

‘출발역’으로부터 출발하여 ‘도착역’으로 한 번 지나간 역은 지나지 않으면서 갈 수 있는 서로


다른 방법의 수를 구하여라.

1. 문제와 알고리즘 193

정보과학-3단원-2차.indd 193 2021-12-20 오전 9:45:39


02
탐구 활동

다음 문제를 분류해 보고, 그 이유를 생각해 보자.

❶ ‌체스판에서 퀸(Queen)은 다음과 같은 범위를 공격할 수 있다. 8×8 크기의 체스판에서 8


개의 퀸들을 서로 공격할 수 없도록 배치할 수 있는가?

❷ 이세돌과 알파고가 재대결한다면, 이세돌은 알파고를 이길 수 있을까?

❸ 위의 문제 ❶을 ‘계수 문제’로 만들어 보고, 해결 방법에 대하여 토의해 보자.

정리
하기 •‌문제는 해결해야 할 대상이며, 문제를 해결한다는 것은 목적 달성을 위한 해법을 만들어내는 것이다.
•‌수학, 과학, 인문·사회학 등 다양한 학문들은 각각이 갖는 특성에 따라 문제 상황을 이해하고, 이를 해결하기
위한 방법을 제시하는 데 의의가 있다.
•‌정보과학은 논리적 연산과 산술적 연산을 조합하여 절차적으로 해결할 수 있는 계산 문제에 관심을 갖는다.
•‌계산 문제는 문제 또는 해결 방법의 특성에 따라 단순 연산 문제, 결정 문제, 계수 문제, 최적화 문제 등으로 나
뉜다.

194 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 194 2021-12-20 오전 9:45:39


읽기 P vs. NP 문제
자료

P 대 NP 문제는 P 문제와 NP 문제가 서로 같음을 증명하라는 것으로서, 미국의 클레이수학연구소(CMI: The Clay
Mathematics Institute)에서 푸는 사람에게 100만 달러의 상금을 주겠다고 하는 7대 난제 중 하나로 유명하다. 이
때 P는 다항식을 뜻하는 영어 단어인 ‘Polynomial’의 약자이며, P 문제는 우리말로 다항 시간 문제(Polynomial time
problem)라고 부른다. 반면, NP는 ‘Non - deterministic Polynomial time problem’의 약자로서 미정 다항 시간 문
제라고 할 수 있다.
P 문제는 문제를 해결하기 위한 알고리즘의 수행 시간을 다항식으로 나타낼 수 있는 문제를 뜻한다. 정렬 문제를 해
결하기 위한 버블, 선택, 삽입, 퀵, 히프 정렬 알고리즘은 리스트를 구성하는 원소의 개수가 n일 때, 수행 시간은 O(n2)
또는 O(nlgn)으로 나타낼 수 있다. 따라서 알고리즘의 수행 시간을 다항식으로 나타낼 수 있으므로 정렬 문제는 P 문
제이다.
반면, NP 문제는 문제를 해결하기 위한 알고리즘의 수행 시간을 다항식으로 나타낼 수 없는 문제를 뜻한다. 대체로
알고리즘의 시간 복잡도가 O(n!) 또는 O(kn) 등인 경우를 말한다. 대표적인 NP 문제로는 ‘해밀턴 경로 문제’, ‘그래프
색칠 문제’, ‘순회 외판원 문제’ 등이 있다.

B
A D

E E

▲▲해밀턴 경로 문제 ▲▲그래프 색칠 문제

▲▲순회 외판원 문제

그렇다면 P와 NP가 같음을 증명하는 것은 어떤 의미일까? 그리고 이것을 해결하는 데 정보과학은 어떤 의미를 가
질까? 이 고민의 시작이 정보과학적 문제 해결의 시작이라고 할 수 있다.

1. 문제와 알고리즘 195

정보과학-3단원-2차.indd 195 2021-12-20 오전 9:45:40


02 알고리즘의 표현과 분석
•알고리즘의 표현 방법을 두 가지 이상 말할 수 있다.
•주어진 알고리즘을 다른 표현 방법으로 표현할 수 있다.

Think 알고리즘을 표현하고 분석한다는 것은 어떤 의미일까?

1 알고리즘의 표현
알고리즘 ‘알고리즘’이란 문제를 해결하는 방법을 뜻하는 것으로, 정보과학 분야에서 다루는 계산
알고리즘은 현재 상태에서 목
표 상태로 이르기 위해 수행해
문제를 해결하기 위한 과정을 절차적으로 나열한 것을 의미한다.
야 하는 순서화된 작업의 나열 계산 문제를 해결하는 과정은 상태 변화를 위한 작업을 찾고 이를 수행하는 것이라 할
이다.
수 있다. 이를 위해서 먼저 문제 분석을 통해 현재 상태와 목표 상태를 파악해야 한다. 그
리고 문제 분해를 통해 현재 상태와 목표 상태를 연결해 주는 중간 상태를 찾아야 한다.
현재 상태 목표 상태

상태 상태 상태 상태
1 2 3 n

수행 작업 1 수행 작업 2 수행 작업 3

알고리즘

▲▲알고리즘을 통한 계산 문제 해결 모델

이러한 관점에서 알고리즘은 현재 상태에서 목표 상태로 상태를 변화시키기 위해 절차


적으로 수행해야 하는 작업의 집합이라고 할 수 있다. 이러한 절차들은 유한 번 내에 종료
되어야 하며, 이를 통해 반드시 문제를 해결할 수 있어야 한다.

알고리즘의 5가지 특성
1. 유한성: 알고리즘은 유한한 횟수 내에서 종료되어야 한다.
2. 명확성: 알고리즘은 명확하게 정의되어야 한다.
3. 입력: 알고리즘은 0개 이상의 입력을 가진다.
4. 출력: 알고리즘은 1개 이상의 출력을 가진다.
5. 효율성: 알고리즘은 다양한 방식으로 문제를 해결할 수 있다.

또한 알고리즘은 반드시 입력과 출력이 있어야 하며, 누가 수행하더라도 결과가 동일해


야 한다. 따라서 알고리즘을 표현할 때는 프로그래밍 언어, 의사 코드, 순서도 등의 도구
나 방법을 이용하여 명확하게 표현해야 한다.

196 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 196 2021-12-20 오전 9:45:40


다음과 같은 입력과 출력을 가지는 문제를 해결하는 방법을 알고리즘으로 표현해 보자.

문제의 모델링
•문제: n개의 수를 가진 배열 S에 값 x가 있는가?
문제 분석 결과를 좌측과 같이
•조건: n은 양의 정수 모델링할 수 있다.
•입력: 1에서 n까지의 첨자를 가진 값의 배열 S, 그리고 값 x
•출력: S 안에 x의 위치를 가리키는 위치, S 안에 x가 없으면 0

위의 문제를 해결하는 알고리즘을 프로그래밍 언어를 이용하여 표현하면 다음과 같다. 프로그래밍 언어를 이용한 알
고리즘 표현
프로그래밍 언어를 이용하면 가장 명확하게 표현할 수 있다는 것이 장점이지만, 특정 언 특정 프로그래밍 언어를 모르
는 사람들은 이해하기 어렵다.
어에 종속된다는 것이 단점이다.

void seqsearch(int n, int S[ ], int x)


{
location = 1;
while(location <= n && S[location]! = x)
location ++;

if(location > n) location = 0;

printf("%d", location);
}

의사 코드
다음은 의사 코드를 이용하여 알고리즘을 표현한 것이다. 의사 코드는 자연어에 가깝게 의사 코드(pseudo code)는
‘pseudo’라는 단어에서 알 수 있
표현할 수도 있으며, 프로그래밍 언어처럼 표현할 수도 있다. 따라서 명확하게 표현할 수
듯이 ‘가짜 코드’라는 뜻이다.
있으면서 특정 언어에 종속되지 않으므로 알고리즘을 표현할 때 자주 활용된다.

[의사 코드 1]
배열 S [1...n]가 주어졌을 때 이 알고리즘은 주어진 인수 k를 S [ ]에서 찾는다. n ≥1이라고 가정한다.
S1. [초기화] i ← 1로 설정한다.
S2. [비교] 만일 k = S[i]이면 i를 출력하고 알고리즘을 끝낸다. 검색에 성공한 것이다.
S3. [전진] i를 1 증가한다.
S4. [파일의 끝?] 만일 i <= N이면 S2로 돌아간다. 그렇지 않으면 검색 실패로 결과는 0을 출력
하고 알고리즘을 끝낸다.

[의사 코드 2]
void seqsearch(int n, const keytype S[ ], keytype x, index location)
{
location = 1

repeat : if location < = n and S[location] ! = x then location ++

1. 문제와 알고리즘 197

정보과학-3단원-2차.indd 197 2021-12-20 오전 9:45:40


if location > n then location = 0
}

순서도의 한계 순서도(flowchart)는 논리의 흐름을 주어진 도형을 이용하여 표현하는 방법으로, 순차,
순서도는 복잡한 알고리즘을
반복 등의 구조를 쉽게 표현한다는 점이 장점이다. 하지만 재귀 함수 등의 관계 표현에서
표현하기에는 한계가 있다.
또한 순서도마다 사용하는 기 의 제약이 있다는 단점이 있다.
호의 종류와 의미가 다를 수도
있다. START START START

i= 0 i= 0 i= 0

sum = 0 sum = 0 sum = 0

i= i+1 i= i+1 i= i+1

sum = sum + i sum = sum +i sum = sum + i

Yes Yes Yes


i < 100 i < = 99 i = 100
No No No
sum 출력 sum 출력 sum 출력
(5050) (5050) (1)

STOP STOP STOP

01
탐구 활동

다음 문제의 알고리즘을 자연어에 가까운 의사 코드를 활용하여 표현해 보자.

•문제: n개의 수로 구성된 리스트 S 에 있는 모든 수의 합을 구하여라.


•입력: 양의 정수 n, 1에서 n까지의 첨자를 가진 값의 배열 S
•출력: S 에 있는 수의 합, sum

198 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 198 2021-12-20 오전 9:45:40


02
탐구 활동

다음 문제의 알고리즘을 프로그래밍 언어와 유사한 의사 코드를 활용하여 표현해 보자.


Tip
•문제: 내림차순으로 n개의 수를 정렬하라.
의사 코드를 이용해 가독성과
•입력: 양의 정수 n, 수의 배열 S (첨자는 1부터 n까지) 명확성을 모두 가진 알고리즘
•출력: 수를 내림차순으로 정렬된 배열 S 으로 표현할 수 있다.

2 알고리즘의 복잡도
정렬과 탐색
계산 문제를 해결하기 위한 알고리즘은 문
정렬 또는 탐색 문제를 해결하
제 분해의 결과에 따라 다양하게 작성될 수 는 알고리즘은 매우 많으며, 효
율도 다르다.
있다. 따라서 동일한 문제를 해결하는 여러
문제의 분해
가지 알고리즘이 존재할 수 있으며, 이러한
설악산 매표소에서 대청봉까
알고리즘 간에 효율의 차이가 있을 수 있다. 지 오르는 경로는 어디를 거쳐
가는지에 따라 달라진다. 이는
다양한 알고리즘 중에서 어떤 것이 더 우수
매표소에서 대청봉까지의 경
한가를 가리기 위한 기준이 바로 알고리즘의 로를 어떻게 분해할 것인지와
관련이 있다.
복잡도(complexity)이다. 알고리즘이 복잡하
다는 것은 수행하는 데 오랜 시간 또는 공간이 효율

필요하다는 것이다. 따라서 알고리즘의 복잡 효율은 효과와 능률의 합성어


이다. 효과는 문제 해결 여부
도는 알고리즘의 효율성, 즉 계산 문제를 해결 를 뜻하는 절대적 기준이며, 능
▲▲설악산을 오르는 다양한 경로 률은 문제 해결의 질을 뜻하는
하는 데 필요한 비용(cost)을 뜻한다.
상대적 기준이다.
복잡도의 척도가 되는 비용에는 컴퓨터로 구현하였을 때 걸리는 시간, 총 연산 수, 사용
된 메모리의 양, 사용된 하드웨어의 양 등이 있다. 비록 어떤 문제가 계산이 가능하다 할
지라도 알고리즘의 복잡도가 너무 크다면 계산하기가 어려울 것이다. 복잡도
컴퓨터는 계산 문제만 해결할
예를 들면, 이론적으로는 모든 경우의 수를 따져 보면 바둑의 최선 전략을 계산할 수 있 수 있으므로 복잡도는 계산 복
잡도와 같은 말이다.
을 테지만, 그 경우의 수는 천문학적으로 많은 수치이므로 이것은 현실적으로 아주 힘든
문제이다.

1. 문제와 알고리즘 199

정보과학-3단원-2차.indd 199 2021-12-20 오전 9:45:41


바둑 문제
바둑 문제는 가능한 수많은 경
우 중에서 가장 유리한 수를
선택하는 과정이다.

▲▲바둑을 해결하는 알고리즘의 복잡도

기본 연산 알고리즘 복잡도의 기준으로 가장 흔히 쓰이는 것은 계산 시간과 총 연산 횟수이다. 계


기본 연산을 무엇으로 선정할
지는 문제나 알고리즘에 따라 산 시간은 기본 연산의 수행 시간에 연산 횟수를 곱한 것과 같다. 따라서 계산 시간과 연
달라질 수 있다. 산 횟수는 사실상 동일한 개념으로 볼 수 있으며, 이를 알고리즘의 시간 복잡도(time
complexity)라고 한다.
알고리즘의 복잡도를 평가하는 다른 기준으로 공간 복잡도(space complexity)라는 것
복잡도
시간 복잡도, 공간 복잡도 모두 도 있다. 입력 데이터의 크기에 따라 어느 정도의 저장 공간이 필요한지를 나타내는 데 사
입력 데이터의 크기에 따른 자
원(시간, 공간)의 사용량을 뜻
용한다. 일반적으로 시간 복잡도에 비해 중요하게 다루지는 않으나, 메모리의 크기가 매
한다. 우 작은 기기에서 알고리즘의 수행에 큰 영향을 줄 수도 있다.

3 시간 복잡도 계산
기본 연산=단위 연산 알고리즘의 시간 복잡도를 분석하기 위해서는 입력의 크기(n)에 대해서 알고리즘의 기
본 연산이 수행되는 횟수를 비교하여 분석하는 기법을 가장 많이 사용한다.
입력의 크기
정렬 또는 탐색 문제의 경우, 입력 크기
원소의 개수가 입력 크기(n)라
고 할 수 있다.
입력 크기(input size)란 투입된 입력 데이터의 크기를 의미한다. 대부분의 알고리즘에서 입력의 크
기를 재는 기준을 찾기는 어렵지 않다.

일반적으로 알고리즘의 실행 시간은 입력의 크기에 따라 증가하고, 총 실행 시간은 기본


연산이 몇 번 수행되는가에 비례한다. 따라서 기본 연산이 수행되는 횟수를 입력의 크기
에 대한 함수로 나타내어 알고리즘의 효율성, 즉 시간 복잡도를 분석할 수 있다.

알고리즘 시간 복잡도
•입력의 크기: n •기본 연산의 실행 횟수: T(n)
•기본 연산의 종류: k •실제 연산의 실행 횟수: k × T(n)
•연산의 하드웨어적 실행 시간: c •총 실행 시간: c × k × T(n)

200 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 200 2021-12-20 오전 9:45:41


알고리즘을 구현한 컴퓨팅 시스템의 하드웨어적인 특성으로 인해 발생하는 소요 시간은
시스템 기종, 언어적 요소, 컴파일러 등에 따라 다르다. 따라서 c와 k를 상수로 놓으면, 알
고리즘의 실행 시간은 입력 자료의 수에 관련 기본 연산의 반복 횟수만으로 분석할 수 있
다. 그러므로 총 실행 시간은 T(n)으로 표현하여도 무방하다.

03
탐구 활동

다음은 배열에 있는 원소의 합을 구하는 알고리즘이다. 이 알고리즘의 성능을 분석해


보자.

sum(int n, S[ ])
{ Tip
result = 0; 제어에 필요한 명령문을 제외
하고 반복 안에 있는 유일한
명령문은 배열의 수를 더하는
for(i = 1; i <= n; i ++)
명령문으로 배열의 수를 더하
result + = S[i]; 는 명령을 기본 연산으로 정의
} 한다.

❶ ‌반복적으로 수행하는 덧셈 연산 하나로 보는 경우의 T(n)

Tip
•기본 연산 기본 연산을 무엇으로 선정하
는지에 따라 시간 복잡도가 다
르게 나타날 수 있다.

•입력 크기

•T (n)

❷ 반복문에 포함된 모든 연산을 기본 연산으로 보는 경우의 T(n)

•기본 연산

•입력 크기

•T (n)

1. 문제와 알고리즘 201

정보과학-3단원-2차.indd 201 2021-12-20 오전 9:45:41


04
탐구 활동

다음은 정렬 알고리즘이다. 이 알고리즘의 성능을 분석해 보자.(단, 기본 연산은 비교 연


산으로 정의한다.)
Tip
sort(int n, S[ ])
오른쪽의 정렬은 인접한 원소
의 값을 비교하여 위치를 교환 {
하는 버블 정렬이다. for(i = 1; i <= n; i ++)
for(j = i + 1; j <= n; j ++)
if(S[j] < S[i])
exchange S[i] and S[j];
}

❶T
‌ (n) 계산

•기본 연산

•입력 크기

•T (n)

❷ 정렬의 과정과 T (n)값과의 관계를 분석해 보자.

202 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 202 2021-12-20 오전 9:45:41


4 최악, 최선, 평균의 경우
알고리즘의 시간 복잡도 분석은 입력의 크기에 대해서 기본 연산을 몇 번 수행하는지를
구하면 된다. 대부분의 시간 복잡도가 일반적으로 입력의 크기에 대해 단위 연산의 수행
횟수가 결정되기 때문이다.
그러나 때로는 입력의 크기 이외에 입력된 값에 따라 기본 연산의 횟수가 가변적일 수
있다. 이런 경우는 시간 복잡도가 임의의 모든 값 x 에 대하여 동일한 횟수만큼의 기본 연
산을 수행하지 않는다.

순차 탐색의 입력
순차 탐색의 경우 찾는 값 x가 배열의 첫 번째 수라면 기본 연산은 한 번이 된다. 그러나 값 x가 배
순차 탐색의 경우 리스트의 원
열에 있지 않거나 마지막 번째 수라면 기본 연산은 n번 수행된다. 소의 개수인 입력의 크기 이외
에도 탐색하고자 하는 값을 입
력한다.
이러한 경우에는 입력값에 따른 최악의 경우, 최선의 경우, 평균적인 경우에 대하여 시
간 복잡도 T(n)을 분석해야 한다. 다음은 순차 탐색 알고리즘에 대한 최악, 최선, 평균 시
간 복잡도를 계산하는 과정이다.

■최악의 경우(worst case) 시간 복잡도: W(n)


x가 배열의 마지막 수이거나 x가 배열에 없으면 기본 연산은 n번 수행되고 이 경우에 기
본 연산이 최대가 된다. 따라서 시간 복잡도 W(n) = n이 된다.

■최선의 경우(best case)인 최소 횟수를 구하는 시간 복잡도: B(n)


입력 크기 n은 항상 1보다 크거나 같으므로 최선의 경우는 찾고자 하는 값 x가 첫 번째에
존재하는 경우로 n의 크기에 관계없이 반복을 수행하는 시간 복잡도 B(n)= 1이 된다.

■평균(average)에 대한 시간 복잡도: A(n)


평균 횟수를 계산하기 위해서는 크기가 n인 입력에 대한 각각의 확률로 계산해야 한다. 평균 횟수는 일종의 기대치
이다.
가용한 정보를 이용하여 확률을 계산하는 것이 중요하다. 순차 탐색의 경우는 두 가지 경
우를 생각해야 한다. 첫째는 찾고자 하는 값 x 가 배열이 있는 경우와 없는 경우에 대한 분
석이 필요하다.
먼저 값 x가 배열에 존재하고 배열 안의 n개의 수가 모두 다르다고 할 때, x가 어떤 특정
위치에 있을 확률은 동일하다. 는 1 ≤ ≤ 이므로 번째 위치할 확률은 1 이다. 만약 가
x k n k x
n
k번째 위치한다면 x를 찾는 데 k번 기본 연산이 수행될 것이다. 따라서 평균 횟수는 다음
과 같다.

1. 문제와 알고리즘 203

정보과학-3단원-2차.indd 203 2021-12-20 오전 9:45:41


두 번째 방법은 x가 배열에 존재할 확률을 이용하는 것이다. 만약 x가 배열에 있을 확률
p
을 p라고 하면, x가 k번째 원소일 확률은 n 이며, k번 동안 탐색 연산을 반복 수행한다. 만
일 x가 배열에 존재하지 않는다면, 이때 확률은 1-p이고, 탐색 연산을 n번 반복 수행한다.
따라서 평균 횟수는 다음과 같다.

(n+1)
여기서 만일 p가 1이면 위에서 살펴본 배열에 x가 존재할 경우와 같이 이 되고 반
2
1 3n 1 3
면에 p가 2 이면 4   +  4이 된다. 이는 평균적으로 4 정도를 기대할 수 있음을 뜻한다.

시간 복잡도 입력의 크기나 값에 따라 동일한 수행 횟수를 가지지 않는 알고리즘에 대하여 최선의 경


일반적으로 가장 많이 사용하
는 것은 최악의 경우에 대한
우나 평균에 의한 분석보다는 최악의 경우 분석을 자주 사용한다. 예를 들어 서버와 클라
시간 복잡도이다. 이언트 사이에 통신이 이루어진다고 할 때, 평균 10ms의 응답 시간을 보여 준다고 해서
평균 시간 복잡도와 최악 시
좋은 네트워크 시스템이라고 보기는 어렵다. 어떤 데이터의 경우는 100ms의 지연 시간
간 복잡도를 함께 표기하기
도 한다. 이 생길 수도 있기 때문이다.
하지만 최악의 경우에도 20ms의 응답 시간을 보여 준다고 할 때에는, 훨씬 더 신뢰성
있는 시스템이라 생각할 수 있다.
알고리즘의 경우에도 마찬가지로, 어떤 특정한 데이터에 대해서만 빠르다면 그 알고리
즘이 좋다고는 할 수 없기 때문이다. 따라서 최선의 경우보다 최악의 경우나 평균적인 경
우를 많이 사용하게 된다.

계산 복잡도→시간 복잡도, 공 ▼ 정렬 및 탐색 알고리즘의 시간 복잡도


간 복잡도
시간 복잡도(Time Complexity)
시간 복잡도 → 최악, 최선, 평균 알고리즘
최선(Best) 평균(Average) 최악(Worst)

퀵 정렬
log log   
(Quick sort)

히프 정렬
log log  log
(Heap sort)
정렬
버블 정렬
       
(Bubble sort)

삽입 정렬
       
(Insertion sort)

순차 탐색
        
(Sequential search)
탐색
2진 탐색
   log log
(Binary search)

204 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 204 2021-12-20 오전 9:46:43


5 점근 표기법
시간 복잡도는 입력의 크기와 기본 연산을 고려하여 알고리즘의 계산 복잡도를 수행 시
간의 관점에서 분석할 때 사용하는 방법이다. 그러나 동일한 문제를 해결하는 알고리즘
간의 효율성을 한눈에 알아보기에 다소 불편하다. 또한 입력의 크기에 따른 수행 시간의
변화 양상을 파악하기에도 별도의 연산이 필요하다는 한계가 있다.

동일한 문제를 해결하는 두 개의 알고리즘 A와 B에 대한 시간 복잡도가 다음과 같을 때 어떤


알고리즘이 더 효율적인가? 모든 n에 대해서 그 결과는 동일한가?
A: T(n) = 3n4 + 31n2 + 17n + 11
B: T(n) = 171n3 + 55n2lgn + nlg n + 4n + 169

점근 표기법(asymptotic notation)이란 알고리즘의 시간 복잡도를 쉽게 비교 및 분석 점근 표기법


점근 표기법은 함수의 변화 정
하고, 특히 입력값의 변화에 따른 수행 시간의 변화 정도를 빠르게 파악할 수 있도록 도와 도를 표현하기 위한 해석학적
주기 위해 사용하는 시간 복잡도의 표현 방법이다. 도구이다.

다양한 점근 표기법 중 일반적으로 많이 사용되는 것이 빅오 표기법(big-O notation) f (n)을 시간 복잡도 함수 T (n)이


라고 할 수 있다.
이다. 빅오 표기법은 주어진 함수 f (n)과 g (n)에 대해서, O(g (n))은 n ≥ n0을 만족하는 모든
n에 대해 다음의 정의를 만족하는 양수 c와 n0가 존재하는 복잡도 함수 g(n)의 집합이라는
해석학적 이론에 기반을 둔다.

정의
O ( g (n)) = { f (n) | 모든 n ≥ n0에 대하여 f (n) ≤ c × g (n)인 양수 c와 n0가 존재한다. }

이것을 f (n)= O(g(n)) 또는 f (n)∈O(g(n))이라고 표기하고 g(n)은 f (n)의 O(big-oh,빅오)


라고 한다. 다음의 그래프에서 n0을 초과하는 모든 n에 대하여 f (n) 이상의 cg(n)이 존재하
므로 g(n)은 f (n)의 점근 시간 복잡도라고 할 수 있다.
cg(n)

f (n)

f (n) = O(g(n))
n0 n
▲▲빅오 표기법의 의미

500
450
400
350
1. 문제와 알고리즘 205
300
250
200
150
100
정보과학-3단원-2차.indd 205 2021-12-20 오전 9:46:43
예를 들어, f (n) = n2 + 10n이라고 가정해 보자. 다음의 그래프에서 n이 10 이상인 지점부
터 f (n) 이상의 값을 가지는 함수 2 × g(n)이 존재한다.

500
450
400
350
2n2
300
250 n2 + 10n
200
150
100
500
50
450
0
400 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

350 ▲▲점근 표기법의 의미


300
그러므로 앞선 O의 250
정의를 만족하는 c와 n0를 취할 수 있다. 따라서 n2 + 10n ∈ O(n2)임
200
을 결론지을 수 있다. 만약 f (n)이 어떤 알고리즘의 시간 복잡도 T(n)이라고 한다면 그 알
150
100000
고리즘의 점근 시간 복잡도인
100 g(n)은 n2이라고 할 수 있고 O(n2)이라고 표현할 수 있다.
10000
50
이것은 이 알고리즘의 수행 시간이 2차 함수 정도가 된다는 뜻이며, 입력의 크기 n이 커
0
1000
질수록 수행 시간이 n 에 비례하여 증가함을 보여 주는 것이다.
2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

100
빅오 표기법을 이용하여 알고리즘의 수행 시간을 분석할 때 주로 사용되는 빅오식은 다
10
음과 같이 그래프로 그려 서로 비교해 볼 수 있다.
1
각 정렬의 시간 복잡도 100000
버블, 삽입, 선택 정렬의 점근 0.1
0.1
10000 1 10 100 1000
시간 복잡도는 O (n2)이다. lgn
퀵 정렬, 히프 정렬의 점근 시 1000 n
간 복잡도는 O (nlgn)이다. nlgn
100
n2
lg 10 n3
n
lg는 밑이 2인 로그를 뜻한다. 2
1 n!
0.1
0.1 1 10 100 1000

▲▲다양한 빅오식

특히 컴퓨터를 이용하여 수행하는 알고리즘의 경우 n값이 큰 경우가 많은데, 빅오 표기


법을 이용하여 점근 시간 복잡도를 구하게 되면 수행 시간이 어디로 수렴하는지를 가늠할
수 있으므로 알고리즘의 효율을 분석할 때 중요한 의미를 갖는다.

206 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 206 2021-12-20 오전 9:46:44


05
탐구 활동

5n2 ∈ O (n2)임을 증명해 보자.

06
탐구 활동

n∈ O (n2)임을 보이고, 이것이 가지는 의미를 시간 복잡도의 상한(upper bound)값의 개


념과 관련지어 설명해 보자.

정리
하기 •알고리즘은 초기 상태를 목표 상태로 전환하기 위해 수행해야 하는 일련의 작업을 나열한 것이다.
•알고리즘은 유한성, 명확성, 입력, 출력, 효율성이라는 조건을 가진다.
•알고리즘은 프로그래밍 언어, 의사 코드, 순서도 등의 도구를 이용하여 명확하게 표현할 수 있다.
•알고리즘의 성능은 계산 복잡도로 나타내며, 계산 복잡도의 종류에는 시간 복잡도와 공간 복잡도가 있다.
•‌시간 복잡도는 입력의 크기와 기본 연산의 수행 횟수를 이용하여 나타낼 수 있으며, 기본 연산을 어떻게 설정하
느냐에 따라 다르게 나타난다.
•점근 표기법은 시간 복잡도를 다양한 관점에서 분석하기 위해 사용하는 해석학적 기법이다.
•‌알고리즘의 성능을 다양한 방식으로 분석함에 따라 프로그래밍을 통해 구현하지 않고도 알고리즘의 효율을 비
교 및 분석할 수 있다.

1. 문제와 알고리즘 207

정보과학-3단원-2차.indd 207 2021-12-20 오전 9:46:44


읽기 오메가 표기법? 세타 표기법?
자료

점근 표기법에는 빅오 표기법 이외에도 오메가()표기법과



 세타()표기법

 등이 있다. 빅오 표기법이 수행 시간의
관점에서 계산 복잡도의 상한값을 알려주는 데 의의가 있다면 오메가 표기법은 하한값을 알려 준다.

f (n)
cg (n)

n0 n
f (n) =(g(n ))

[정의]
g(n ))={ f (n)|모든
 ( n ≥n0에 대하여 f (n)≥c ×g(n)인 양수 c와 n0가 존재한다.}
[예시]
3n2 ∈  (n2), 5n3 + 7 ∈  (n2)

또한 세타 표기법은 수렴값이 동일한 함수들의 집합을 나타내기 위해 사용한다.

c2g (n)
f (n)
c1g (n)

n0 n
f (n ) =  (g(n ))

[정의]
 (g(n)) = { f (n) | 모든 n≥n0에 대하여 c1×g(n) ≤ f (n) ≤ c2×g(n)인 양수 c1, c2, n0가 존재한다.}
즉,  (g (n)) = O( g(n))∩(g (n))이다.

[예시]
3n2 - 2n ∈  (n2)

208 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 208 2021-12-20 오전 9:47:21


프로젝트 수행하기

정렬 알고리즘 효율의 연역적 분석

정렬 알고리즘의 효율은 다음의 절차에 따라 연역적으로 분석할 수 있다.

❶ 두 원소의 값을 비교하는 연산을 기본 연산을 정의한다.

❷ 원소의 개수(n)와 비교 연산의 횟수를 이용하여 시간 복잡도 T (n)을 구한다.


❸ 최악의 경우에 대하여 빅오 표기법을 이용한 시간 복잡도를 구한다.

❹ 시간 복잡도를 이용하여 알고리즘의 효율을 비교한다.

1 과제 1 선택 정렬, 퀵 정렬의 시간 복잡도를 연역적으로 분석하고 비교해 보자.

2 과제 2 선택 정렬, 퀵 정렬의 공간 복잡도에 대해 알아보자.

중단원 마무리 209

정보과학-3단원-2차.indd 209 2021-12-20 오전 9:47:21


탐색 기반 알고리즘
컴퓨터는 빠르고 정확한 계산이 가능한 기기이다. 따라서 문제 해결에 컴퓨터를 이용하면 정확성과 신속성 측
면에서 보다 효율적인 해결이 가능하다.
문제를 해결하는 기본적인 접근 방법 중 ‘해’가 존재할 수 있는 공간을 탐색하면서 문제를 해결하는 방식이 있
다. 예를 들어 ‘용의자들 중에서 범인을 찾는 문제’, ‘상대방이 마음속에 생각하고 있는 100 이하의 자연수 1개를
맞히는 문제’ 등이 여기에 해당한다.
이러한 방식으로 문제를 해결하기 위해 작성된 알고리즘을 탐색 기반 알고리즘이라고 한다. 또한 해가 존재할
수 있는 공간을 탐색 공간이라고 한다. 탐색 공간의 크기가 크면 해를 찾는 데 오랜 시간이 걸리지만, 컴퓨터가 가
진 빠르고 정확한 계산 능력을 이용한다면 매우 효율적으로 문제를 해결할 수 있다.
그렇다면 탐색 기반 알고리즘을 설계하는 구체적인 방법이 있을까? 그리고 탐색 기반 알고리즘의 효율을 높이
려면 어떻게 해야 할까?

3차원 탐색 공간

3차원으로 표현된 탐색 공간

210 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 210 2021-12-20 오전 9:47:22


01 탐색 기반 알고리즘 설계
•탐색 기반 알고리즘의 개념과 특성에 대해 이해할 수 있다.
•탐색 알고리즘과 탐색 기반 알고리즘 설계 방법에 대해 이해할 수 있다.

Think 탐색을 통해서 문제를 해결한다는 것은 무슨 뜻일까?

1 탐색 기반 알고리즘의 개념
‘탐색 기반 알고리즘’이란 컴퓨팅 시스템의 탐색 능력을 기반으로 문제 해결을 위한 해
를 찾는 알고리즘을 뜻한다. 또한 이러한 알고리즘을 효율적으로 설계하기 위한 방법을
탐색 기반 알고리즘 설계 방법이라고 한다.
탐색을 통해 문제를 해결한다는 것은 선형 자료 구조인 배열 또는 리스트 등에서 원하
는 자료를 찾거나, DB 등에서 사용자가 원하는 자료를 찾기 위해 검색하는 것을 예로 들
수 있다. 또한 비선형 자료 구조인 트리 또는 그래프 등에서 원하는 자료를 찾는 행위, 또
는 주어진 문제를 해결하는 과정 중 문제 공간에서 해를 찾는 것도 이에 포함된다. 그리고
탐색한 해의 개수를 세는 계수(counting) 문제, 탐색한 해 중 가장 품질이 좋은 해를 찾는 최적해 탐색 문제
최적화 문제를 최적해 탐색 문
최적화(optimization) 문제 등도 이에 포함할 수 있다. 제라고도 한다.

▲▲탐색 알고리즘에 관한 인포그래픽

2 탐색 기반 알고리즘 설계 방법
효율적인 탐색 기반 알고리즘을 설계하는 첫 번째 과정은 먼저 해가 존재할 수 있는 집 탐색 공간
탐색 공간이란 후보 해들의 집
합을 설정하는 것이다. 이러한 집합은 탐색의 대상이 되므로 탐색 공간이라고 부른다. 효 합을 뜻한다.

율적인 탐색 기반 알고리즘을 설계하는 첫 번째 방법은 탐색 공간을 체계적으로 구조화하


는 것이다. 예를 들어, 다음과 같이 보조 기억 장치에 저장된 다양한 명령 또는 데이터를
파일이라고 하며, 파일을 모아 놓은 공간을 폴더라고 부른다.

2. 탐색 기반 알고리즘 211

정보과학-3단원-2차.indd 211 2021-12-20 오전 9:47:22


▲▲파일과 폴더

폴더는 효율적인 파일 관리를 위해 파일에 부여한 속성 중 하나로서, 폴더를 어떻게 구


성하느냐에 따라 파일의 관리, 즉 삽입, 삭제, 특히 탐색의 효율이 크게 달라진다. 따라서
원하는 파일을 찾기 위해서는 폴더를 효율적으로 구성하여야 한다.
탐색 알고리즘은 이렇게 구조화한 데이터의 형태에 따라 선형 탐색과 비선형 탐색으로
구분한다. 선형 탐색은 리스트, 큐, 스택 등 선형적으로 구조화된 탐색 공간을 대상으로
한다. 또한 비선형 탐색은 트리, 그래프 등과 같이 비선형적으로 구조화된 공간을 탐색하
는 알고리즘이다.

탐색 공간의 구조 탐색 방법 탐색 알고리즘

순차 탐색
선형 구조 선형 탐색
2진 탐색

깊이 우선 탐색
비선형 구조 비선형 탐색
너비 우선 탐색

탐색 기반 알고리즘의 효율 효율적인 탐색 기반 알고리즘을 설계하는 두 번째 과정은 탐색하는 대상의 수, 즉 탐색


탐색 기반 알고리즘의 효율을
높이기 위해서는 탐색 공간의
공간의 크기를 줄이는 일이다. 탐색 공간의 크기에 따라 탐색 시간이 달라지기 때문이다.
크기를 줄여야 한다. 가장 기본적인 방법은 탐색 공간 전체를 탐색하는 것이다. 이러한 탐색 기반 알고리즘 설
계 방법을 전체 탐색 또는 완전 탐색이라고 한다.
전체 탐색은 탐색 공간 전체에서 해가 될 수 있는 원소를 찾는 방법으로, 컴퓨팅 시스템
의 빠르고 정확한 계산 능력에 의존하는 방식이다. 그러나 컴퓨팅 시스템의 계산 속도가
아무리 빠르다고 하더라도, 탐색 공간의 크기가 매우 큰 경우에는 합리적인 시간 내에 해
를 찾지 못할 수 있다. 이럴 때는 적절한 관계나 조건을 이용하여 탐색 공간을 줄여야 한
다. 부분 탐색 알고리즘이란 탐색 공간의 일부만을 탐색함으로써 해를 찾는 알고리즘을

212 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 212 2021-12-20 오전 9:47:23


뜻한다. 일반적으로 수학적 접근 또는 경험적 접근을 통해 탐색 공간의 일부를 제외하는
방식이다. 이를 탐색 공간의 배제라고 한다.

탐색 대상 탐색 기반 알고리즘

탐색 공간의 전체 전체 탐색

탐색 공간의 일부 부분 탐색

01
탐구 활동

다음의 주제에 관해 토론하고 발표해 보자.

❶ 파일을 효율적으로 찾기 위해 적절한 폴더 구조는 무엇인가?

❷ 일상생활 속에서 선형 탐색과 비선형 탐색의 예를 찾아보자.

❸ 수학 문제를 풀다가 전체 탐색을 한 경험과 부분 탐색을 한 경험에 대해 이야기해 보자.

정리
하기 •탐색 기반 알고리즘 설계 방법은 효율적인 탐색 알고리즘을 설계하기 위한 것이다.
•탐색 알고리즘은 컴퓨터의 빠르고 정확한 계산 능력을 기반으로 한다.
•‌탐색 기반 알고리즘을 설계하기 위해서는 효율적인 자료 구조를 설계하고, 탐색 공간의 크기를 줄이는 것이 필
요하다.

2. 탐색 기반 알고리즘 213

정보과학-3단원-2차.indd 213 2021-12-20 오전 9:47:23


02 전체 탐색
•전체 탐색 알고리즘 설계 방법의 개념과 특성에 대해 이해할 수 있다.
•전체 탐색 알고리즘 설계 방법을 이용하여 알고리즘을 설계하고 프로그래밍을 통해 구현할 수 있다.

Think 전체 탐색 알고리즘은 어떻게 만들까?

1 전체 탐색 알고리즘 설계 방법
알고리즘과 알고리즘 설계 방법 ‘전체 탐색 알고리즘 설계 방법’이란 해가 존재할 수 있는 전체 공간을 모두 탐색하면서
알고리즘 설계 방법과 알고리
해를 찾는 알고리즘을 설계하는 방법으로서, 완전 탐색법 또는 전 탐색법 등으로 불린다.
즘은 다른 의미이다.
알고리즘을 설계하기 쉬운 반면, 탐색 시간이 오래 걸리는 경우 합리적인 시간 내에 해를
찾지 못할 수도 있다는 단점이 있다.

문제 공간
탐색 공간을 문제 공간이라고
부르기도 한다.

▲▲N queens 문제를 전체 탐색을 통해 해결하는 과정

문제에 따라 탐색 공간의 크기가 다르며, 때로는 매우 큰 공간을 탐색해야 하는 경우도


있다. 이러한 경우에 전체 탐색 알고리즘을 바탕으로 문제를 해결하는 데 어려움이 발생
한다. 그러나 컴퓨터의 빠른 계산 능력을 이용하면 허용 가능한 탐색 공간의 크기가 생각
보다 클 수 있기 때문에 매우 유용하게 사용할 수 있는 방법이다.

214 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 214 2021-12-20 오전 9:47:23


좌표평면에서 다음 조건을 만족시키는 정사각형 중 두 함수 y = log3x,
y = log7x의 그래프와 모두 만나는 것의 개수를 구하시오.

(가) 꼭짓점의 x좌표, y좌표가 모두 자연수이고 한 변의 길이가 1이다.


(나) 꼭짓점의 x좌표는 모두 100 이하이다.

y
3

2 y = log7x
y = log3x
1

0 1 2 3 4 5 6 7 x
<출처 > 대학수학능력시험 9월 모의 평가, 2012년

▲▲모두 구하려면 전체 탐색을 해야 하지 않을까?

따라서 전체 탐색 알고리즘 설계 방법은 컴퓨터의 계산 능력에 대한 의존도가 높은 방


법이라고 할 수 있다. 이러한 의미에서 전체 탐색을 통해 문제를 해결하는 알고리즘을 브
루트 포스 알고리즘(brute-force algorithm), 또는 소모적 탐색 알고리즘(exhaustive
search algorithm)이라고 부르기도 한다.

01
탐구 활동

일상생활 속에서 전체 탐색 알고리즘을 설계하여 문제를 해결해 본 경험에 대해 토론하


고 발표해 보자.(단, 컴퓨터를 사용하지 않은 사례도 좋다.)

❶ 주어진 문제 상황

❷ 적용했던 탐색 알고리즘

❸ 문제 해결 여부와 탐색 공간의 크기 간의 관계

2 선형 전체 탐색
탐색 기반 알고리즘을 설계하기 위해서 가장 먼저 할 일은 탐색 공간을 구조화하여 표현
하는 일이다. 이렇게 해야만 탐색의 정확성과 신속성을 높일 수 있는 효율적인 알고리즘
을 설계할 수 있기 때문이다.

2. 탐색 기반 알고리즘 215

정보과학-3단원-2차.indd 215 2021-12-20 오전 9:47:23


▲▲원하는 물건을 빠르고 정확하게 찾으려면, 먼저 정리가 필요!

따라서 자료가 정리된 구조와 탐색 알고리즘을 설계하는 과정은 매우 밀접한 관련을 가


지게 된다. 자료 구조에 따라 탐색 전략이 달라질 수 있기 때문이다. 선형 전체 탐색이란,
선형적으로 구조화된 탐색 공간을 일련의 절차를 통해 탐색하는 알고리즘을 뜻한다.
일반적으로 선형 전체 탐색 알고리즘을 설계하기 위해서는 탐색 공간을 선형적으로 구
조화하여 표현하고, 이를 순차 탐색 또는 2진 탐색을 통해 탐색하면 된다.
예를 들어, 10 이하의 자연수 n의 모든 약수의 합을 구하는 문제가 주어졌다고 가정해
일반항의 시간 복잡도 보자. 만약 수학 시간에 위와 같은 문제가 제시되었다면, 이 문제를 해결하기 위한 일반
일반항은 입력의 크기(n)와 관
계없이 상수 횟수의 연산만을
항을 구하고자 시도할 것이다. 물론 일반항의 시간 복잡도는 O (1)로서 가장 우수한 알고
수행한다. 따라서 일반항의 시 리즘으로 평가된다. 그러나 이러한 방법을 기억하거나 또는 구상하기가 쉽지 않기 때문에
간 복잡도는 O (1) 이다.
문제를 해결하기 어려운 것이다.
이 문제를 해결하기 위해 첫 번째로 할 일은 탐색 공간을 구조화하는 것이다. 예를 들어
10의 약수를 구하는 방법을 알고리즘으로 접근하려면, 10의 약수가 될 수 있는 모든 자연
수로 구조화할 수 있다. 일단 10의 약수가 될 수 있는 자연수를 집합으로 표현하면 다음과
같다.
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

이와 같이 문제의 해가 될 수 있는 자료를 선형적으로 표현할 수 있으며, 이를 배열이나


리스트와 같은 자료 구조를 바탕으로 저장할 수 있다.
두 번째 단계로 구조화한 자료에서 원하는 해를 탐색한다. 선형적인 자료 구조에서 활용
할 수 있는 탐색 방법은 순차 탐색 알고리즘이다. 따라서 첫 번째 원소부터 마지막 원소까
지 순차적으로 탐색하면서 10의 약수를 찾는다.

216 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 216 2021-12-20 오전 9:47:23


탐색 과정에서 탐색 공간을 구성하는 원소 중 10의 약수인 수는 남기고, 10의 약수가
아닌 수는 배제해 보자. 이때 10의 약수란 10을 현재 원소로 나누어 떨어지는 수이다. 따
라서 탐색 과정을 끝낸 후의 집합은 다음과 같이 정리된다.

{ 1, 2, 5, 10 }
마지막으로 탐색 결과를 통해 남겨진 원소들의 합을 계산함으로써 다음과 같이 문제를
해결할 수 있다.
1 + 2 + 5 + 10 = 18
따라서 문제의 해는 18이다. 이렇게 절차적으로 접근하여 문제를 해결하면 컴퓨터가 없
어도 쉽게 해를 구할 수 있다. 만약 탐색 공간의 크기가 커진다면 똑같은 절차로 컴퓨터를
활용하여 쉽게 구할 수 있다.
또한 위의 문제 해결 과정에서 입력받는 값을 n으로 일반화하면 다음과 같은 알고리즘
을 설계할 수 있다.

[n의 모든 약수의 합을 구하는 알고리즘, 단, n은 100 이하의 자연수]


sum ← 0
for i ← 1 to n step 1
if n ≡ 0 ( mod i )
sum ← sum + i
end if
end for
print sum

마지막으로 이를 자동화하기 위해 다음과 같은 소스 코드를 작성할 수 있다.

해보기 1 n의 모든 약수의 합

프로그램
01 #include <stdio.h >
02 int main( )
03 {
04 int n, i, sum = 0;
05 scanf("%d", &n);
06
07 for(i = 1; i <= n ; i ++)
08 if(n%i == 0) sum + = i;
09
10 printf("%d\n", sum);
11 }

2. 탐색 기반 알고리즘 217

정보과학-3단원-2차.indd 217 2021-12-20 오전 9:47:24


02
탐구 활동

정수 n을 입력받아 n 이하의 자연수 중 3 또는 5의 배수의 합을 구하는 프로그램을 작


성해 보자.(단, n은 100 이하의 자연수)

❶ 탐색 공간을 구조화해 보자.

❷ 선형 전체 탐색 알고리즘을 설계하고, 의사 코드로 표현해 보자.

❸ 선형 전체 탐색 알고리즘을 프로그래밍을 통해 구현해 보자.

218 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 218 2021-12-20 오전 9:47:24


03
탐구 활동

길이가 n(cm) 인 철사가 있다. 이 철사 중 두 군데를 구부리면 삼각형을 만들 수 있다. n


이 주어질 때, 두 곳을 구부려 만들 수 있는 서로 다른 모든 삼각형의 수를 구하는 프로
그램을 작성해 보자. 아래는 9cm일 때의 예를 나타낸다.

4 4 3 3 5
3

3 4
1

❶ 탐색 공간을 구조화해 보자.

❷ 선형 전체 탐색 알고리즘을 설계하고, 의사 코드로 표현해 보자.

❸ 선형 전체 탐색 알고리즘을 프로그래밍을 통해 구현해 보자.

❹ ‌시간 복잡도와 탐색 공간 간의 관계를 고려하여, 전체 탐색 알고리즘의 효율을 높일 수 있


는 방법에 대해 토론하고 발표해 보자.

2. 탐색 기반 알고리즘 219

정보과학-3단원-2차.indd 219 2021-12-20 오전 9:47:24


3 비선형 전체 탐색
‘비선형 전체 탐색’이란 비선형적으로 구조화된 탐색 공간을 탐색하여 해를 찾는 알고리
즘을 뜻한다. 따라서 비선형 전체 탐색 알고리즘을 설계하기 위해서는 제일 먼저 문제 상
황을 분석하여 탐색 공간을 비선형적으로 구조화하여야 한다.
비선형 자료 구조의 형태로 구조화된 탐색 공간은 트리 또는 그래프의 형태로 나타낼 수
있다. 따라서 이 공간을 탐색하기 위해서는 깊이 우선 탐색 또는 너비 우선 탐색을 적용할
깊이 우선 탐색의 구현 수 있으며, 일반적으로 구현이 간단한 깊이 우선 탐색을 많이 사용한다.
깊이 우선 탐색은 재귀 함수를
이용하여 쉽게 구현할 수 있다.
a a

b c b c

d e f g d e f g

h i j k h i j k

▲▲깊이 우선 탐색 ▲▲너비 우선 탐색

비선형 전체 탐색은 문제를 해결하기 위해 고려해야 하는 조건을 바탕으로 깊이 우선 탐


색을 진행하면서 해를 찾는 알고리즘이다. 이렇게 한정 조건을 가진 문제를 비선형적인
탐색 공간으로 표현하고, 깊이 우선 탐색을 바탕으로 문제를 해결하는 방법을 퇴각 검색
또는 백트래킹(backtracking)이라고 한다.
예를 들어 탐색 공간이 다음과 같이 비선형적으로 구조화되어 있다고 가정해 보자. 이때
원하는 해를 찾기 위해 트리의 노드를 탐색하는 과정은 기본적으로 깊이 우선 탐색의 과
정과 유사하다.

▲▲탐색 공간이 비선형적으로 구조화된 경우

위와 같은 트리 구조에서 맨 위 노드에서 출발하여 모든 노드를 깊이 우선 탐색한다고


할 때, 처음 3단계의 탐색 과정은 다음과 같다.

220 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 220 2021-12-20 오전 9:47:24


1 1 1

2 2

▲▲깊이 우선 탐색의 방문 순서

위 그림과 같이 1단계부터 3단계까지 진행하면 더 이상 깊이 파고 들어갈 곳이 없다. 이


경우 3번째로 방문한 노드에서 다시 2번째 방문한 노드, 즉 부모 노드로 되돌아가야만 다
시 다른 노드를 깊이 우선 탐색할 수 있다. 이 과정을 백트랙이라고 한다.

▲▲백트랙

따라서 백트래킹은 백트랙을 바탕으로 전체 탐색을 수행한다는 의미의 의태어이다.


백트래킹은 재귀 함수를 이용하여 간단하게 구현할 수 있으므로, 다양한 문제를 해결하
는 데 유용하게 사용할 수 있다. 그러나 입력 크기(n)가 증가함에 따라 탐색 공간의 크기가
기하급수적으로 비례하는 단점이 있다. 이렇게 되면 입력값에 따라 합리적인 시간 내에
해를 구할 수 없게 된다.
예를 들어, 다음과 같이 자연수 n을 자연수의 합으로 나타낼 수 있는 모든 순열의 개수
를 구하는 문제가 주어졌다고 가정해 보자.

입력 출력 설명

1. (1, 1, 1)
2. (1, 2)
3 4
3. (2, 1)
4. (3)

이 문제를 전체 탐색 알고리즘을 설계하여 해결하기 위해 가장 먼저 해야 할 것은 탐색


공간의 구조화이다. 이를 통해 선형 전체 탐색 또는 비선형 전체 탐색 알고리즘을 설계해
야 하기 때문이다.

2. 탐색 기반 알고리즘 221

정보과학-3단원-2차.indd 221 2021-12-20 오전 9:47:24


입력값 n이 3이라고 할 때, 해를 찾아가는 과정을 다음과 같이 도식화할 수 있다. n을
자연수의 합으로 표현해야 하기 때문에 루트 노드인 3에서 뻗어 나가는 간선은 최대 3개
이다. 3
1 2 3

▲▲n이 3일 때의 예

합해서 3이 되는 순열을 구하는 문제이므로, 가장 왼쪽 간선부터 마지막에 1, 2, 3을 더


해서 3이 되는 것을 의미한다고 할 수 있다. 따라서 레벨 2의 노드들의 값은 좌측부터 2,
1, 0이고, 이를 도식화하면 다음과 같다.

3
1
2 3

2 1 0

▲▲레벨 1과 레벨 2의 모습

레벨 2의 마지막 노드는 값이 0이고 루트 노드까지 연결하는 간선에 부여된 가중치가 3


이다. 따라서 하나의 해라고 할 수 있다. 위 그림과 같은 트리를 확장하여 값이 0인 노드
를 모두 찾아보자.
3
1
모든 순열을 찾는 깊이 우선 2 3
탐색
2 1 0
입력값 n에 대하여 모든 노드의 1
자식 노드가 최대 n개까지 생성
2 1
되는 n진 트리가 만들어진다. 1 0 0
1
0
▲▲모든 순열을 찾은 모습

위 트리에서 노드의 값이 0인 경우는 3을 자연수의 합으로 표현하는 경우를 뜻한다. 이


때 루트 노드부터 단말 노드까지 이어진 간선의 가중치를 왼쪽부터 살펴보자. 가장 왼쪽
의 노드부터 차례대로 1+1+1, 1+2, 2+1, 3으로 나타나며, 문제에서 구하고자 했던 순
열의 개수는 모두 4가지임을 알 수 있다.
이 문제를 해결했던 과정을 되짚어 보자. 가장 먼저 탐색 공간의 구조를 알아내기 위해
탐색 과정을 분석하였다. 루트 노드의 값인 자연수 n에 대하여 최대 n개의 자식 노드가
만들어진다. 이렇게 생성된 자식 노드에 대하여 또다시 최대 n개의 자식 노드가 만들어진
다. 결국 문제 해결을 위해 탐색해야 하는 공간이 비선형적 자료 구조인 n진 트리의 형태
로 나타난다.

222 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 222 2021-12-20 오전 9:47:24


앞에서 제시했던 것처럼 n이 작은 수인 경우에는 사람이 직접 트리의 노드를 전개해
가면서 해결할 수 있다. 이때 탐색한 값이 0인 노드는 결국 합이 n인 순열과 관계가 있기
때문에 이 노드의 개수를 세어 보면 문제가 해결된다. 그러나 n이 큰 수라면 값이 0인 노
드를 찾는 것과 이것을 세는 것이 쉽지 않다. 이때 적용할 수 있는 것이 비선형적으로 구
조화된 문제 공간을 탐색하면서 해를 찾아가는 비선형 전체 탐색 알고리즘, 즉 백트래킹
이다.
또한 문제 해결 과정에서 입력받는 값을 n으로 일반화하면, 다음과 같은 알고리즘을 설
계할 수 있다.

[자연수 n을 자연수의 합으로 나타낼 수 있는 모든 순열의 개수를 구하는 알고리즘]

BT(n)
if n <= 0
2진 트리 형태의 탐색 공
if n = 0
간을 도식화하고, 이를 백
sum ← sum + 1 트래킹으로 탐색하려면
end if 어떻게 해야 할까?
backtrack
for i ← 1 to n step 1
dfs(n - i)
end for
end BT
print sum

마지막으로 이를 자동화하기 위해 다음과 같은 소스 코드를 작성할 수 있다.

해보기 2 자연수 n을 자연수의 합으로 나타낼 수 있는 모든 순열의 개수

프로그램
01 #include <stdio.h >
02 int sum;
03
04 void f(int n)
05 {
06 int i;
07 if(n <= 0)
08 {
09 if(n == 0) sum ++;
10 return; // backtrack
11 }
12 for(i = 1; i <= n; i ++)

2. 탐색 기반 알고리즘 223

정보과학-3단원-2차.indd 223 2021-12-20 오전 9:47:24


13 f(n - i);
14 }
15
16 int main( )
17 {
18 int n;
19 scanf("%d", &n);
20 f(n);
21 printf("%d\n", sum);
22 }

04
탐구 활동

주어진 n×n 행렬에서 n개의 원소를 행과 열이 중복되지 않도록 선택할 때 얻을 수 있는


최소합을 구해 보자. 다음은 n이 3일 때의 행렬의 예시이다.(단, n은 5 이하의 자연수)

153
247
535

❶ 전체 탐색을 위한 비선형 탐색 공간을 구조화해 보자.

❷ 전체 탐색 알고리즘을 설계하고, 의사 코드로 표현해 보자.

224 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 224 2021-12-20 오전 9:47:25


❸ 전체 탐색 알고리즘을 프로그래밍을 통해 구현해 보자.

05
탐구 활동

N * N 체스판에 N개의 퀸을 서로 공격하지 못하도록 배치하는 모든 경우의 수를 구해 보 Tip


N - Queens 문제라고 불리는
자. 다음은 N이 4일 경우에 퀸을 서로 공격하지 못하게 배치한 사례 중 하나이다.
전체 탐색 문제이다.

❶ 전체 탐색을 위한 비선형 탐색 공간을 구조화해 보자.

2. 탐색 기반 알고리즘 225

정보과학-3단원-2차.indd 225 2021-12-20 오전 9:47:25


❷ 전체 탐색 알고리즘을 설계하고, 의사 코드로 표현해 보자.

❸ 전체 탐색 알고리즘을 프로그래밍을 통해 구현해 보자.

정리
하기 •전체 탐색 알고리즘 설계 기법은 탐색 공간 전체를 탐색하면서 해를 찾는 알고리즘을 만드는 방법이다.
•전체 탐색 알고리즘은 탐색 공간의 구조에 따라 선형 전체 탐색과 비선형 전체 탐색으로 나뉜다.

226 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 226 2021-12-20 오전 9:47:25


03 탐색 공간의 배제
•전체 탐색 알고리즘의 효율을 높이기 위해 탐색 공간을 배제하는 알고리즘을 설계할 수 있다.
•효율적인 문제 해결을 위해 탐욕 알고리즘과 분기한정 알고리즘을 프로그래밍을 통해 구현할 수 있다.

Think 탐색 공간을 줄일 수는 없을까?

1 탐색 공간의 배제
탐색 알고리즘은 해가 존재할 수 있는 공간을 모두 탐색하면서 해를 찾는 알고리즘으로, 탐색 알고리즘의 효율
탐색 알고리즘의 효율은 탐색
컴퓨터의 빠르고 정확한 계산 능력에 의존하는 알고리즘 설계 방법이다. 따라서 탐색 알 공간의 크기에 영향을 받는다.

고리즘의 시간 복잡도는 탐색 공간의 크기에 따라 다양하게 나타난다.

▲▲바둑의 탐색 공간은 모두 얼마일까?

이때 O(n2), O(n3) 등 지수 형태의 시간 복잡도를 가지는 알고리즘이나 O(n!) 등 팩토리


얼 형태의 시간 복잡도를 가지는 알고리즘의 경우, 입력 변수인 n이 커지면 수행 시간이
기하급수적으로 늘어난다. 이로 인해 때때로 합리적인 시간 내에 문제를 해결하기 어려운
상황이 발생한다.
그러나 탐색 공간의 크기는 문제의 특성이므로 문제를 바꾸지 않는 한 줄이거나 늘리는
것이 본질적으로 불가능하다. 때로는 문제 분석을 효과적으로 함에 따라 탐색 공간이 줄
어들 때가 있지만, 이것은 애초에 문제 분석이 잘못되었던 것이다.

2. 탐색 기반 알고리즘 227

정보과학-3단원-2차.indd 227 2021-12-20 오전 9:47:25


▲▲알파고는 그 많은 탐색 공간을 모두 탐색했을까?

탐색 전략 탐색 알고리즘의 효율을 높이기 위한 두 번째 방법은 탐색 전략을 바꾸는 일이다. 예를


들어 주어진 문제를 해결하기 위해 전체 탐색을 할 경우 O(n3)의 시간 복잡도를 가지는 알
탐색 전략이란 탐색 공간을 탐
색해 나가는 형태이므로 탐색
구조라고도 할 수 있다. 고리즘이 불가피하다고 할 때, 적절한 전략을 활용하여 O(n2),O(n) 등의 알고리즘으로 해
를 찾도록 설계하는 것이다. 탐색 공간의 배제란, 효율적인 탐색 전략을 설계함으로써 탐
색 공간의 크기를 줄이는 효과를 가져오는 알고리즘 설계 방법을 뜻한다. 같은 의미에서
부분 탐색이라고도 한다.

01
탐구 활동

일상생활 속에서 다음과 같은 과정을 통해 문제를 해결해 본 경험에 대해 토론하고 발표


해 보자.(단, 컴퓨터를 사용하지 않은 사례도 좋다.)

문제를 접할 때는 ‘이 많은 것들을 어떻게 다 해 보나?’라는 생각을 했다. 주어진 시간은


부족한데, 따져 봐야 할 경우(case)가 많았기 때문이다. 그런데 조금 더 생각을 해 본 결
과, 모든 경우를 다 해 보지 않고도 해결할 수 있는 방법이 있음을 알게 되었다. 이 방법
을 적용해 보니 처음에 생각했던 것보다 적은 시간을 들여서 문제를 해결할 수 있다.

❶ 문제 상황

228 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 228 2021-12-20 오전 9:47:25


❷ 처음에 생각한 알고리즘과 시간 복잡도

❸ 나중에 생각한 알고리즘과 시간 복잡도

2 탐욕 알고리즘 설계 방법
전체 탐색 공간 중 일부를 배제하여 효율적으로 문제를 해결하는 방법 중 하나는 탐욕
알고리즘을 설계하는 것이다. 탐욕 알고리즘(greedy algorithm)이란 현재 상태에서 다
음 상태를 탐색할 때 모든 상태를 고려하지 않고, 최선의 상태만을 고려하여 선택하는 알
고리즘 설계 방법으로 욕심쟁이 알고리즘 또는 그리디 알고리즘이라고 불린다. 이 방법은
탐색 공간 상에 여러 개의 해가 존재할 때 이들 중에 가장 적절한 해를 찾는 최적화 문제 최적화 문제와 탐색
최적화 문제의 경우, 가능한 경
를 해결할 때 유용하게 적용할 수 있다. 우를 모두 탐색하는 방법 이외
에도 그리디 알고리즘으로 해
결할 수도 있다.

▲▲두 지점을 연결하는 최단 경로를 찾는 효율적인 방법은?

2. 탐색 기반 알고리즘 229

정보과학-3단원-2차.indd 229 2021-12-20 오전 9:47:25


최대 합 경로 문제는 최적화 예를 들어, 다음과 같은 그래프에서 루트 노드부터 단말 노드로 이동하고자 한다. 이때 노
문제의 일종이다.
드의 합이 최대가 되는 경로가 무엇인지 구하는 문제가 주어졌다고 가정해 보자.

8 2

4 3 9

1 5 2 1

▲▲루트 노드에서 단말 노드의 최대 합 경로 문제

이 문제를 전체 탐색 방법을 적용하여 해결한다면 어떨까? 루트 노드부터 두 번째 레벨


의 모든 노드까지의 합을 계산하고, 또 여기서부터 세 번째 레벨의 합을 계산하는 등의 과
정을 모든 단말 노드까지 반복해야 한다. 현재 탐색 공간은 높이가 n인 그래프이므로 전체
탐색 알고리즘의 시간 복잡도는 O(n2)이다. 따라서 n이 커짐에 따라 수행 시간이 기하급수
적으로 늘어날 것이며, 아주 큰 값을 가진 n에 대해서는 합리적인 시간 내에 해를 구할 수
없을 것이다.
그렇다면 이 문제를 탐욕 알고리즘 설계 방법을 이용하여 해결하면 어떨까? 먼저 루트 노
드에서 출발해야 하므로, 현재 상태는 루트 노드이며 이때까지 합은 3이다. 루트 노드에서
선택할 수 있는 경로는 값이 8인 왼쪽 자식 노드와 값이 2인 오른쪽 자식 노드이다.
탐욕 알고리즘은 현재 상태에서 다음 상태를 탐색할 때 최선의 상태만을 고려하는 알고리
즘 설계 방법이다. 주어진 문제가 최대 합 경로를 찾는 문제이므로, 루트 노드에서의 선택은
값이 8인 왼쪽 자식 노드일 것이다.
같은 방식으로 단말 노드까지의 경로를 선택하는 과정을 다음과 같이 도식화할 수 있다.
이를 통해 얻은 결과는 20이다. 루트 노드부터 단말 노드까지 거쳐 온 경로 상의 노드의 값
최대 합 경로 문제에 적용한 이 각각 3, 8, 4, 5이기 때문이다. 이와 같이 탐욕 알고리즘 설계 방법을 적용하면 탐색 문제
탐욕 알고리즘의 시간 복잡도
는 O (n) 이다. 의 해를 간단하게 구할 수 있다는 장점이 있다.

8 2

4 3 9

1 5 2 1

▲▲탐욕 알고리즘을 적용한 결과

230 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 230 2021-12-20 오전 9:47:25


그러나 탐욕 알고리즘의 탐색 구조에 있어서 논리적 비약이 있다. 현재 상태에서 다음
상태로 이동할 때 값이 큰 노드를 선택하였는데, 이러한 선택이 전체 공간에서의 최대 합
을 보장한다는 논리적 근거가 없기 때문이다. 따라서 이렇게 해서 얻어진 해가 최적해임
을 보장하기 어렵다는 문제가 발생한다. 예를 들어, 아래와 같은 자료 구조에 대해 탐욕
알고리즘을 적용한다면 어떨까?

8 2

4 3 9

1 5 2 8

▲▲탐욕 알고리즘이 항상 최적해를 보장할까?

그렇다면 탐욕 알고리즘을 사용하는 이유는 무엇일까? 이 문제에서 탐욕 알고리즘을 통


해 얻은 해인 20과 실제 최적해인 22를 비교해 보자. 그 차이가 큰가? 일반적으로 그렇지
않다.
탐욕 알고리즘이 항상 최적해임을 보장하는 것은 아니지만 비교적 질 좋은 해를 쉽고 간
단하게 구할 수 있다. 전체 탐색을 적용할 때의 시간 복잡도인 O(n2)이 O(n)으로 줄어들지
않았는가?
탐욕 알고리즘을 통해 항상 올바른 해를 구하기 위한 방법은 없을까? 탐욕 알고리즘의
핵심이 탐색 영역의 분할에 있음을 기억해 보자. 현재 상태에서 취할 수 있는 다음 상태
중에서 이득이 되는 것은 취하고, 그렇지 않은 것을 버리는 방식이기 때문이다.
따라서 탐색 공간을 취하거나 버리는 선택이 명확할 수 있는 문제의 경우에 탐욕 알고리
즘 설계 방법을 적용하면 정확한 해를 구할 수 있다. 이를 위해서 필요한 것이 바로 논리
적 근거이다.

$4 12kg
$2 2kg

$2 1kg 15kg
$1
1kg

$10
4kg

▲▲배낭에 담을 수 있는 물건의 최대 가치는?

2. 탐색 기반 알고리즘 231

정보과학-3단원-2차.indd 231 2021-12-20 오전 9:47:26


02
탐구 활동

100 이하의 자연수 n의 모든 약수의 합을 구하는 탐욕 알고리즘을 설계하고, 프로그래밍


을 통해 구현해 보자.

❶ 탐욕 알고리즘을 설계하기 위한 전략을 세워 보자.

1부터 n까지의 선형 탐색
공간을 모두 탐색할 필요
가 있을까?

❷ 탐욕 알고리즘을 설계해 보자.

❸ 탐욕 알고리즘을 프로그래밍해 보자.

03
탐구 활동

◯◯ 나라에서 사용하는 동전은 1원, 5원, 10원, 50원으로 구성되어 있다. ◯◯ 나라의
자동판매기에는 다음과 같이 거스름돈을 지불하기 위한 탐욕 알고리즘이 설계되어 있다
고 할 때, 다음에 대해 토론하고 발표해 보자.

232 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 232 2021-12-20 오전 9:47:26


예를 들어, 760원의 거스름돈에 대하여
① 500원 동전 1개로 지불한다.
따라서 남은 돈은 260원이 된다.(760 - 500 × 1 = 260)
② 100원 동전 2개로 지불한다.
따라서 남은 돈은 60원이 된다.(260 - 100 × 2 = 60)
③ 50원 동전 1개로 지불한다.
따라서 남은 돈은 10원이 된다.(60 - 10 × 1 = 10)
④ 10원 동전 1개로 지불한다.
따라서 남은 돈은 0원이 되므로 종료된다.(10 - 10 × 1 = 0)

❶ 제시한 탐욕 알고리즘의 논리적 근거를 설명해 보자.

❷ 탐욕 알고리즘을 프로그래밍해 보자.

❸ 제시한 탐욕 알고리즘을 적용할 수 없는 상황에 대해 생각해 보자.

2. 탐색 기반 알고리즘 233

정보과학-3단원-2차.indd 233 2021-12-20 오전 9:47:26


3 분기한정 알고리즘 설계 방법
탐색 공간을 배제하여 탐색 알고리즘의 효율
을 높이기 위한 또 하나의 방법은 탐색 경험에
근거하여 특정 지역의 탐색 필요 여부를 판단하
는 방법이다. 즉, 탐색 과정에서 더 이상 탐색
할 필요가 없다고 판단되는 경로에 대해서 탐색
을 진행하지 않고, 백트랙을 수행하는 방식이라

분기한정 고 할 수 있다. 이것을 분기한정(branch and


▲▲과실나무의 가지를 치는 이유는?
분기한정 알고리즘 설계 방법 bound) 알고리즘 설계 방법이라고 한다.
은 노드가 뻗어 나가는 간선을
제거하는 방법이므로 일종의 얼핏 보면, 탐색의 효율을 높이기 위해 이득을 취할 수 있는 행위를 한다는 점에서 탐욕
가지치기라고 할 수 있다.
알고리즘과 유사해 보인다. 그러나 탐욕 알고리즘과는 달리 분기한정 알고리즘은 정확한
근거를 바탕으로 탐색을 제한하는 알고리즘이므로 항상 최적해를 보장한다.
일반적으로 깊이 우선 탐색(DFS)의 형태로 전체 탐색을 진행하다가 탐색이 불필요한
노드가 발견되면 백트랙을 수행한다. 예를 들어, 다음과 같은 탐색을 해야 하는 비선형 탐
색 공간이 있다고 가정해 보자. 이때 노드 내부의 번호는 탐색 순서를 뜻한다. 만약 2번에
서 3번으로 진행하려고 할 때, 3번 이하의 모든 노드를 더 이상 탐색할 필요가 없다고 판
단할 방법이 있다면 바로 9번으로 진행할 수 있다.

1 1

2 10 2 5

3 9 11 3 9 6

4 7 4 7

5 6 8 5 6 8

▲▲분기한정을 위한 백트랙

전체 탐색을 했다면 탐색 횟수가 11회가 되었을 상황에서 분기한정 알고리즘을 설계하


여 6회만에 동일한 결과를 얻는 알고리즘을 구현할 수 있게 되었다. 따라서 보다 효율적
인 탐색을 수행할 수 있도록 하는 부분 탐색 알고리즘 설계 기법이라고 할 수 있다.

234 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 234 2021-12-20 오전 9:47:26


04
탐구 활동

다음의 문제를 해결하는 알고리즘을 설계하고, 프로그래밍을 통해 해결해 보자.

◯◯ 나라에서 사용하는 동전은 10원, 50원, 60원, 100원, 500원으로 구성되어 있다.
◯◯ 나라에서 790원의 거스름돈을 지불할 수 있는 최소 동전의 개수를 구해 보자.

❶ 전체 탐색 알고리즘을 설계해 보자.

❷ 분기한정 알고리즘을 설계할 수 있는 근거(정보)를 찾아보자.

❸ 분기한정 알고리즘을 이용하여 프로그래밍해 보자.

정리
하기 •전체 탐색 알고리즘의 효율을 높이기 위해서는 불필요한 공간을 탐색에서 배제해야 한다.
•탐색 공간의 일부를 탐색함으로써 전체 탐색의 효과를 내는 알고리즘을 부분 탐색 알고리즘이라고 한다.
•현재 상태에서 가장 이득이 되는 다음 상태만을 고려하는 방법을 탐욕 알고리즘이라고 한다.
•탐욕 알고리즘은 최적해를 보장하지 못한다.
•‌전체 탐색의 과정에서 얻은 정보를 바탕으로 불필요한 영역의 탐색을 제한하는 방법을 분기한정 알고리즘이라
고 한다.
•분기한정 알고리즘은 정확한 근거를 가지고 수행되므로 언제나 최적해를 보장한다.

2. 탐색 기반 알고리즘 235

정보과학-3단원-2차.indd 235 2021-12-20 오전 9:47:26


읽기 알고리즘과 휴리스틱
자료

알고리즘이란 문제를 해결하는 방법과 절차이다. 따라서 문제 해결을 위해 설계한 알고리즘은 주어진 문제 상황에
서 반드시 문제를 해결할 수 있어야 한다.
그러나 문제의 특성상 알고리즘을 설계하더라도 해결이 어려운 문제가 있다. 대체로 시간 및 공간의 제약 때문이
다. 즉, 알고리즘의 시간 복잡도와 공간 복잡도가 좋지 않기 때문이다. 이는 컴퓨터를 이용하여 계산할 때도 마찬가지
이다.
따라서 이러한 문제들을 위한 새로운 접근이 필요하다. 휴리스틱(heuristic)이란 발견법이라는 뜻으로, 합리적인 시
간 및 공간 내에서 해결이 불가능한 문제들을 해결하는 데 활용되는 방법이다. 매우 거대한 탐색 공간을 가진 최적해
탐색 문제를 해결하는 과정에서 대체로 해에 가까울 것이라 예상되는 해를 빠르게 찾기 위한 방법이 대표적인 예이다.
Selection Expansion Simulation Backpropagation

12/21 12/21 12/21 11/22

7/10 5/8 0/3 7/10 5/8 0/3 7/10 5/8 0/3 7/11 5/8 0/3

2/4 5/6 1/2 2/3 2/3 2/4 5/6 1/2 2/3 2/3 2/4 5/6 1/2 2/3 2/3 2/4 5/7 1/2 2/3 2/3

2/3 3/3 2/3 3/3 2/3 3/3 2/3 3/4

0/0 0/0 0/1

0·1
▲▲몬테카를로 트리 탐색

이러한 관점에서 “명확한 근거는 없지만 대략 그럴 것이다.”라는 근거로 수행되는 탐욕 알고리즘도 일종의 휴리스틱
이라고 할 수 있다. 알파고(AlphaGo)에 적용된 몬테카를로 탐색법이나 8-퍼즐 문제를 해결하는 데 활용하는 A* 탐
색 알고리즘 등도 휴리스틱의 한 예이다.

2 8 3 1 2 3 f (n)
1 6 4 8 4 g (n)
7 5 7 6 5 h (n)
( 4= 0+4 ) 목표 노드

2 8 3 2 8 3 2 8 3
1 6 4 1 4 1 6 4
7 5 7 6 5 7 5
( 6= 1+5 ) ( 4= 1+3 ) ( 6= 1+5 )

2 8 3 2 3 2 8 3

▲▲8-퍼즐 문제를 해결하는 A* 탐색 알고리즘

236 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 236 2021-12-20 오전 9:47:27


프로젝트 수행하기

1 ‌과제 1 ‌일상생활 속에서 전체 탐색을 통해 해결해야 하는 문제 상황을 발견해 보고, 탐색 공간의 크기를 분석
해 보자.

2 과제 2 이 문제를 전체 탐색으로 해결하기 위한 알고리즘을 설계하고 프로그래밍을 통해 구현해 보자.

3 과제 3 이 문제의 탐색 효율을 높이기 위한 방법을 제시하고, 효율을 비교 및 분석해 보자.

중단원 마무리 237

정보과학-3단원-2차.indd 237 2021-12-20 오전 9:47:27


관계 기반 알고리즘
컴퓨터를 이용하여 해결하는 문제는 복잡한 문제이다. 간단한 문제를 해결할 때 컴퓨터를 사용하는 것은 비용
측면에서 매우 비효율적이기 때문이다.
복잡한 문제를 해결하는 방법 중 하나는 문제를 해결이 용이한 작은 단위로 분해하고, 분해된 작은 문제들 간의
‘관계’를 기반으로 알고리즘을 설계하는 방식이 있다. 예를 들어 ‘1부터 100까지의 합을 구하는 문제’, ‘피보나치수
열의 n번째 항을 구하는 문제’ 등이 여기에 해당한다.
이러한 방식으로 문제를 해결하기 위해 작성된 알고리즘을 관계 기반 알고리즘이라고 한다. 관계를 기반으로
알고리즘을 설계하기 위해서는 문제의 분해와 관계의 정의가 필요하다. 특히 정의된 관계의 구조에 따라 효율적인
알고리즘을 설계할 수 있다.
그렇다면 관계 기반 알고리즘을 설계하는 구체적인 방법이 있을까? 그리고 이러한 알고리즘을 설계해야 하는
이유는 무엇일까?

재귀적 관계를 바탕으로 만들어진 프랙털 나무

var ctx = canvas.getContext('2d'),


generation = 0,
branchLength = 60;

ctx.translate(200, 360);
branch(0);

function branch(angle)
{

generation ++;

ctx.save( );

ctx.rotate(angle);
ctx.scale(0.85,0.85);

ctx.beginPath( );
ctx.moveTo(0, 0);
ctx.translate(0, -branchLength);
ctx.lineTo(0, 0);
ctx.stroke( );

if(generation <= 12)


{

branch( 0.3);
branch(-0.3);
}

ctx.restore( );

generation--;

238 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 238 2021-12-20 오전 9:47:28


01 관계 기반 알고리즘 설계
•문제 분해와 관계 정의의 개념을 이해할 수 있다.
•전체 문제와 부분 문제 간의 재귀적 관계를 정의할 수 있다.

Think 관계를 바탕으로 문제를 해결한다는 것은 무슨 뜻일까?

1 문제 분해와 관계
일상생활이나 다양한 학문 분야의 문제를 해결하기 위해서는 문제를 해결하는 방법을
알아야 한다. 그러나 때로는 문제를 해결하는 방법을 알고 있음에도 불구하고 해결하지
못하는 문제가 있다. 이러한 문제들은 우리 주변에서 쉽게 발견할 수 있다.

f (n)  =  1 ×2 ×3 ×  ... ×  n


g (n)  =1 +2 +3 +  ...  +  n

위의 예시에서 알 수 있듯이, g (n)의 경우 n의 크기에 관계없이 바로 계산할 수 있는 일


반항이 존재한다. 그러나 f (n)의 경우, 보다 빠르고 쉽게 계산할 수 있는 알고리즘이 존재
하지 않는다. 따라서 f (n)은 n에 비례하는 횟수만큼 계산해야만 해결할 수 있다.
이러한 문제를 복잡한 문제(complex problem)라고 한다. 복잡한 문제는 여러 번의 계
산 과정을 거쳐야 해결되므로, 이때 사용한 알고리즘의 계산 횟수가 시간 복잡도이다.
f (n)을 n에 비례하는 횟수만큼 계산해야 한다는 것은 f (n)이 한 번에 해결되지 않는다는
뜻이다. 따라서 f (n)을 계산하는 과정을 다음과 같이 추상화할 수 있다.

현재 상태 목표 상태
g (1) g (n)

g (1) g (2) g (3) g (n - 1) g (n)


▲▲문제 분석과 분해

복잡한 문제를 해결하기 위해서는 가장 먼저 문제의 현재 상태와 목표 상태를 발견해야


한다. 이것을 문제 분석 또는 상태 분석이라고 한다. 그러나 복잡한 문제는 현재 상태에서
목표 상태로 단번에 이동할 수 있는 방법이 없다.
따라서 여러 과정과 단계를 거쳐야 한다. 이때 어떠한 과정이나 단계를 거쳐야 하는지를 문제의 분해
g(n)을 구하는 문제는 g(1), g(2)
알아내야만 알고리즘을 설계할 수 있으며, 이러한 단계는 결국 전체 문제를 해결하기 위 … g(n -1)을 구하는 문제들로
해 해결해야만 하는 부분 문제들을 의미한다. 나눌 수 있다.

3. 관계 기반 알고리즘 239

정보과학-3단원-2차.indd 239 2021-12-20 오전 9:47:28


•전체 문제: 복잡한 문제의 원래 모습
•부분 문제: 복잡한 문제를 분해하여 얻은 작은 문제들
•관계: 전체 문제를 구성하는 부분 문제들의 구조

문제 분해란 전체 문제를 부분 문제로 나누는 과정을 뜻한다. 이렇게 분해된 문제들 사


이에는 구조화된 관계가 존재하게 된다. 관계 정의란 부분 문제들 사이의 구조를 수식,
표, 다이어그램, 언어 등을 통해 명확하게 표현하는 것을 말한다.
특히 계산 문제를 해결하기 위해서는 전체 문제와 부분 문제 간의 관계를 논리적이고 명
확한 수식으로 표현하는 것이 바람직하다. 팩토리얼 문제의 경우, 각 문제 간의 관계를 다
음과 같이 표현할 수 있다.

f (1)  =   1
f (2)  =  f (1) × 2
f (3)  =  f (2) × 3
f (4)  =  f (3) × 4
▲▲전체 문제와 부분 문제의 관계

2 재귀적 관계와 점화식


전체 문제와 부분 문제 간의 관계를 정의하는 과정에서 각 문제 간의 관계가 일관성을
가지는 경우를 발견할 수 있다. 예를 들어, 팩토리얼 문제의 경우 현재 상태인 f (k)와 다음
상태인 f (k + 1) 간에 곱셈 관계의 일관성이 성립한다.
이것은 팩토리얼 문제를 구성하는 모든 작은 문제들의 직전 상태들과 다음 상태 간의 관
계에 특별한 규칙이 있음을 뜻하는 것이며, 따라서 다음과 같이 목표 상태인 f (n)을 이전
상태들을 이용하여 일반화하여 정의 내릴 수 있다.

f (1)  =   1
f (2)  =   f (1)×2
f (3)  =   f (2)×3
f (4)  =   f (3)×4
...

f (n)  =   f (n -1)×n


▲▲문제 분해를 통해 파악한 재귀적 관계

전체 문제와 부분 문제 간의 관계가 재귀적으로 표현될 수 있다면, 이를 점화식으로 나


타낼 수 있다. 점화식(recurrence formula)이란 일반항을 한 개 이상의 앞선 항들을 이

240 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 240 2021-12-20 오전 9:47:28


용하여 나타낸 식을 뜻한다. 즉, 일반항을 이전의 다른 항들과의 관계를 이용하여 정의한 수학적 귀납법
수학적 귀납법은 증명 방법이
재귀적인 관계식이다. 점화식을 표현하기 위해서는 초항과 관계식을 정의해야 한다. 며, 점화식은 계산을 위한 관계
식이다.
1. 함수 정의: f (n)  =   1×2×3×...×n
2. 초항 : f (1)  =   1
3. 관계식 : f (k + 1)  =   f (k) × (k + 1)

▲▲재귀적 관계를 이용하여 설계한 점화식

재귀적 관계(recursive relation)를 점화식으로 표현하면 재귀 함수를 이용한 프로그


래밍 과정을 통해 쉽게 구현할 수 있다. 따라서 문제 분해를 통해 재귀적 관계를 파악하는
것은 알고리즘 설계에 있어서 매우 중요한 과정이다. 다음은 n이 6일 때의 팩토리얼 함수
의 수행 과정이다.
(factorial 6)
(* 6 (factorial 5))
(* 6 (* 5 (factorial 4)))
(* 6 (* 5 (* 4 (factorial 3))))
(* 6 (* 5 (* 4 (* 3 (factorial 2)))))
(* 6 (* 5 (* 4 (* 3 (* 2 (factorial 1))))))
(* 6 (* 5 (* 4 (* 3 (* 2 1)))))
(* 6 (* 5 (* 4 (* 3 2))))
(* 6 (* 5 (* 4 6)))
(* 6 (* 5 24))
(* 6 120)
720
▲▲(factorial 6)의 재귀적 수행 과정

01
탐구 활동

다음은 일반적으로 사용하는 월간 계획표이다. 이에 관한 다음의 물음에 대해 토론하고,


발표해 보자.
[ ]월 계획표
SUN MON TUE WED THU FRI SAT

3. 관계 기반 알고리즘 241

정보과학-3단원-2차.indd 241 2021-12-20 오전 9:47:28


❶ 월간 계획표의 목표는 무엇인가?

❷ 전체 문제와 부분 문제는 무엇인가?

❸ 문제 간의 관계를 어떻게 정의하고 있는가?

242 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 242 2021-12-20 오전 9:47:28


02
탐구 활동

피보나치수열에 대한 다음 물음에 대해 토론하고, 발표해 보자.

❶ 전체 문제와 부분 문제는 무엇인가?

❷ 전체 문제와 부분 문제의 관계를 재귀적으로 정의해 보자.

정리
하기 •전체 문제는 부분 문제로 분해하여 해결한다.
•전체 문제를 구성하는 부분 문제들의 구조를 관계라고 한다.
•계산 문제의 관계는 계산 가능한 형태로 명확하게 표현되어야 한다.
•재귀적 관계란 전체 문제의 해결 구조와 부분 문제의 해결 구조가 동일한 형태일 때의 관계를 뜻한다.
•재귀적 관계로 표현된 문제는 알고리즘 설계 및 구현이 효율적이다.

3. 관계 기반 알고리즘 243

정보과학-3단원-2차.indd 243 2021-12-20 오전 9:47:29


02 동적 계획법
•하향식 동적 계획법을 이용한 알고리즘을 설계하고 구현할 수 있다.
•상향식 동적 계획법을 이용한 알고리즘을 설계하고 구현할 수 있다.

Think 인간 게놈 프로젝트는 어떻게 성공할 수 있었을까?

1 관계식을 이용한 알고리즘 설계


문제를 부분 문제들과의 관계를 이용하여 알고리즘을 설계하면 효율적으로 해결할 수
있다. 이는 탐색을 통해 해를 찾아가는 탐색 기반 알고리즘 설계 방법과는 다른 방식의 알
고리즘 설계 방법이다.
A7
A8
A5
A6
A3
A4

A0 A1

A2

▲▲동일한 형태로 분해해야 한다.

관계식을 이용하여 알고리즘을 설계할 때에는 부분 문제를 정의하고 부분 문제들 간의


재귀적 관계를 설정하는 것이 중요하다.
따라서 전체 문제와 부분 문제의 해결 구
조가 동일하도록 문제를 적절히 분해하여
야 한다. 이를 통해 재귀적 관계가 정의되
면 재귀 함수를 이용하여 쉽게 구현할 수
있다.
예를 들어, 어떤 문제의 입력값이 n일 경
▲▲도미노를 모두 쓰러뜨리려면?
우의 해를 f (n)이라고 하자. n>k 인 k일 때
문제의 해는 f (k)라고 하면, f (k)는 f (n)과 해결 구조는 같지만 크기가 작은 문제이다.
f (n)과 f (k)와의 관계를 다음과 같은 관계식으로 표현할 수 있다면 f (n)은 f (k)를 이용하여
분할(divide)되었다고 한다.

244 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 244 2021-12-20 오전 9:47:29


f (n)= f (k)+c ... ①
여기서 c 는 문제의 특성에 따라 하나의 상수가 될 수도 있고 함수이거나 수식일 수도 있
다. 이 식은 점화식을 구성하는 관계식이므로 이 식만으로는 문제를 해결할 수 없다.
점화식에 초항이 필요하듯이 f (k)들 중 더 이상 분할하지 않더라도 직접 해를 구할 수 있는
크기를 a라고 하고 이때 직접 구한 해가 r 이라고 한다면, 다음과 같은 식을 만들 수 있다.
f (a)= r ... ②
이와 같이 문제를 직접 해결할 수 있을 때까지 더 작은 부분 문제로 분할해 가면서 문제
를 해결하는 기법을 ‘분할정복법’이라고도 한다. 분할정복법으로 만들어진 대표적인 알고 분할정복법
일반적으로 재귀적으로 문제
리즘으로 퀵 정렬이 있다. 를 작은 문제로 분할하고 그
이상의 과정을 통해 얻어 낸 관계식 ①과 함수식 ②를 이용하여 다음과 같이 점화식으로 결과를 이용하여 문제를 해결
하는 설계 방법을 분할정복법
표현할 수 있다. 이라고 한다. 좁은 의미로는 알
r (n = a)
f (n)= { f (k)+c (n≠a, n >k)
고리즘의 효율 향상을 위하여
문제를 작은 문제로 분할할 때
같은 크기의 작은 문제들로 분
할하는 방법만을 의미하기도
이와 같이 표현된 점화식은 재귀 함수를 이용하여 다음과 같이 구현할 수 있다. 결국 f (a) 한다.
는 분해된 문제 중 가장 작은 부분 문제이고, 특별히 분할하지 않고도 곧바로 해를 구할
수 있는 문제라고 할 수 있다.

[f(n)을 분할정복하여 해를 구하는 알고리즘]


f(n)
if n = a
f(n) ← r
else
f(n) ← f(k) + c
end if
end f

이상의 과정을 통해 분할정복법을 이용하여 알고리즘을 설계하는 과정은 점화식을 설계


하는 과정과 동일하다는 것을 알 수 있다. 그렇다면 분할정복을 이용한 알고리즘이 항상
올바른 해를 구할 수 있을까?
이것은 재귀적 관계를 바탕으로 작성한 점화식을 수학적 귀납법을 통해 증명할 수 있는
지 판단하는 문제와 동치이다. 즉, f (n)이 정의된 상태에서, 가장 작은 부분 문제의 해를 찾
고, 이를 바탕으로 f (n)을 그보다 작은 문제인 f (k)를 이용한 관계식으로 표현하면 되기 때
문이다. 따라서 분할정복법을 통해 문제를 해결하기 위해서는 올바른 점화식을 구성하는
것이 가장 중요하다.

3. 관계 기반 알고리즘 245

정보과학-3단원-2차.indd 245 2021-12-20 오전 9:47:29


다음은 분할정복법의 점화관계식을 구성하는 과정을 나타낸 것이다.

❶ 전체 문제를 함수의 형태로 정의한다. 이때 함수는 반드시 값을 가질 필요는 없다.


❷ 바로 정복할 수 있는 최소 크기의 문제를 함수식으로 표현한다.
❸ 큰 문제와 작은 문제의 관계를 정의한다.

예를 들어, 1부터 n까지의 합을 구하는 문제를 분할정복을 통하여 해결해 보자. 가장 먼


저, 주어진 문제를 다음과 같이 함수의 형태로 정의해야 한다. 이는 궁극적으로 해결해야
하는 목표 상태라고 할 수 있다.
f (n)은 1부터 n까지의 합
다음으로 할 일은 분할할 필요 없이 한 번에 정복할 수 있는 최소 크기의 문제를 함수식
으로 표현하는 일이다. 수학적 귀납법에서의 초항을 찾는 일과 같다. 위에서 정의한 f (n)
을 구하는 문제에 있어서 f (1)은 분할할 필요 없이 바로 정복할 수 있는 현재 상태이다.

f (1)= 1
분해 이렇게 되면 이 문제는 현재 상태인 f (1)에서 목표 상태인 f (n)으로 나아가기 위한 문제
문제를 보다 쉽게 해결할 수
있는 작은 문제를 나눔
가 된다. 이 사이에는 다양한 상태들이 존재하는데, 이들 간의 재귀적 관계를 정의하기 위
해서는 문제를 동일한 크기로 분할해야 한다.
분할
큰 문제를 동일한 구조의 작은 현재 상태 목표 상태
문제로 나눔
f (1) f (n)
정복
f (1) f (2) f (3) f (n - 1) f (n)
분할된 문제의 해를 얻음
▲▲현재 상태와 목표 상태

이렇게 동일한 크기로 문제를 분할하면 어떠한 k 에 대해서도 다음의 관계식이 성립함
을 알 수 있다.
f (k)= f (k -1)+k
이상의 과정을 정리하면 다음과 같은 점화식을 얻을 수 있다.

(n = 1)
{ f (n -1)+n (n ≠1)
1
f (n)=

위의 점화식을 분할정복 알고리즘으로 표현하면 다음과 같으며, 이는 재귀 함수를 통해


쉽게 구현할 수 있다.

246 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 246 2021-12-20 오전 9:47:29


[1부터 n까지의 합을 구하는 분할정복 알고리즘]
f(n)
if n = 1
f(n) ← 1
else
f(n) ← f(n - 1) + n
end if
end f

01
탐구 활동

100의 모든 약수의 합을 구하는 문제가 있다. 이 문제를 해결하는 분할정복 알고리즘을


설계하고, 프로그래밍을 통해 구현해 보자.

❶ 함수 f (n)을 정의해 보자.


Tip
f (n)의 정의에 따라 의미 없는
분할이 발생할 수 있다.

❷ 초항을 정의해 보자.

❸ 점화식을 설계해 보자.

3. 관계 기반 알고리즘 247

정보과학-3단원-2차.indd 247 2021-12-20 오전 9:47:29


❹ 분할정복 알고리즘을 설계하고, 프로그래밍을 통해 문제의 해를 구해 보자.

02
탐구 활동

자연수 n을 입력받아 ‘*’을 이용하여 직각 삼각형 모양의 구조를 출력하는 프로그램을 작


성해 보자. 예를 들어 아래 그림은 n이 3일 때의 출력 결과이다.

*
**
***

❶ 함수 f (n)을 정의해 보자.

❷ 초항을 정의해 보자.

248 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 248 2021-12-20 오전 9:47:29


❸ 점화식을 설계해 보자.

❹ 분할정복 알고리즘을 설계하고, 프로그래밍을 해 보자.

2 하향식 동적 계획법
‘동적 계획법(dynamic programming)’이란, 전체 문제와 부분 문제의 관계를 바탕으 동적 계획법
니들만-분쉬(N e e d l e m a n
로 재귀적으로 정의된 문제를 해결한 결과를 일일이 기록하는 과정을 통해 문제를 해결하 -Wunsch) 알고리즘은 인간의
유전체 지도를 만들기 위한 인
는 알고리즘의 설계 방법이다. 이러한 기록을 위해서 별도의 메모리 공간을 필요로 하며,
간 게놈 프로젝트에 활용된 대
일반적으로 배열을 이용한다. match = 1 mismatch = 1 gap = 1 표적인 동적 계획법 알고리즘
이다.
이렇게 사용하는 배열 공간의 G C A T G C U
값은 문제의 해결, 즉 정복 과정 0 –1 –2 –3 –4 –5 –6 –7
에서 지속적으로 갱신되기 때문
G –1 1 0 –1 –2 –3 –4 –5
에 동적 테이블(dynamic table)
A –2 0 0 1 0 –1 –2 –3
이라고도 부른다. 따라서 동적
T –3 –1 –1 0 2 1 0 –1
계획법은 재귀적 관계로 정의된
T –4 –2 –2 –1 1 1 0 –1
문제의 해결을 위해 동적 테이블
A –5 –3 –3 –1 0 0 0 –1
을 이용하는 방식이라고 할 수
C –6 –4 –2 –2 –1 –1 1 0
있다.
동적 계획법은 문제를 해결하 A –7 –5 –3 –1 –2 –2 0 0

는 방향에 따라 하향식 동적 계 ▲▲니들만 - 분쉬 알고리즘의 동적 테이블

3. 관계 기반 알고리즘 249

정보과학-3단원-2차.indd 249 2021-12-20 오전 9:47:30


획법과 상향식 동적 계획법으로 나눈다. 하향식 동적 계획법은 재귀적 관계를 바탕으로
설계한 분할정복 알고리즘을 재귀 호출을 통해 구현하는 과정에서 발생할 수 있는 계산의
중복 문제를 해결하기 위해 사용하는 방법이다.
하향식 동적 계획법은 분할된 문제의 계산 결과를 별도로 기록하는 방식으로 중복을 배
제한다. 따라서 하향식 동적 계획법을 메모이제이션(memoization) 알고리즘이라고도 부
른다.

▲▲같은 길을 계속해서 돌면 시간이 오래 걸린다.

하향식 동적 계획법, 즉 메모이제이션이 필요한 상황에 대해 생각해 보자. 어떠한 문제


를 전체 문제와 부분 문제 간의 관계를 재귀적으로 정의할 수 있다면 분할정복 방법을 통
해 알고리즘을 설계하고 구현하기가 용이하다. 그러나 분할의 과정에서 작은 문제들의 중
복이 발생하면 엄청난 시간의 낭비가 발생한다.
예를 들어, 자연수 n을 입력받아 피보나치수열의 n번째 항을 구하는 문제를 생각해 보
자. 피보나치수열의 정의에 따라 손쉽게 점화식을 얻을 수 있다.

(n = 1, 2)
{ f (n -1)+f (n -2) (n ≥3)
1
f (n)=

이러한 재귀적 관계에 기반하여 다음과 같은 분할정복 알고리즘을 설계할 수 있다.

[피보나치수열의 n번째 항을 구하는 분할정복 알고리즘]


f(n)
if n = 1 or n = 2
f(n) ← 1
else
f(n) ← f(n - 1) + f(n - 2)
end if
end f

그리고 다음과 같이 재귀 함수를 이용한 프로그래밍을 통해 구현할 수 있다.

250 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 250 2021-12-20 오전 9:47:30


해보기 1 분할정복 알고리즘을 적용한 피보나치수열 문제

프로그램
01 #include <stdio.h >
02
03 int f(int n)
04 {
05 if(n == 1 || n == 2)
06 return 1;
07 else
08 return f(n - 1) + f(n - 2);
09 }
10
11 int main( )
12 {
13 int n;
14 scanf("%d", &n);
15 printf("%d\n", f(n));
16 }

이 프로그램을 실행해 보면 n의 값이 작을 때는 빠른 시간 내에 f (n)의 값을 얻을 수 있


다. 그러나 어느 정도 큰 값을 입력하면 매우 오랜 시간에 걸쳐 계산을 하게 되며, 심지어는
합리적인 시간 내에 해를 얻지 못한다는 사실을 알 수 있다. 이러한 상황이 발생되는 이유는
프로그램이 수행하는 재귀 호출 및 반환 과정을 분석함으로써 쉽게 파악할 수 있다.

f (n) 이 그림에서 알 수 있듯이 f (n - 2)는 2번 호출되


고 계산된다. 또한, f (n - 3)은 3번 호출되고 계산
된다. 이것을 전체 노드에 대해 확장해서 생각하면,
f (n- 1) f (n- 2)
매우 많은 계산이 중복되어 수행됨을 알 수 있다.

이와 같이 부분 문제가 중복하여 등장하는 경우


f (n- 2) f (n- 3) 는 한 문제를 두 개 이상의 부분 문제로 분할할 때

발생할 수 있다. 이러한 부분 문제의 중복은 분할정


f (n- 3) f (n- 4) 복법의 효율을 매우 떨어뜨리기 때문에 부분 문제
재귀 호출 횟수
의 중복이 발생되는 경우는 분할정복법을 활용하여

재귀 호출 횟수와 계산 횟수는
▲▲재귀 호출 및 반환 과정 비례한다.
해결하기에 적합한 문제가 아니다.
조금 더 자세한 분석을 위해 입력값 n을 1부터 40까지 증가시킴에 따라 요구되는 계산
횟수를 세어 보고, 그 결과를 파일 출력을 바탕으로 시각화하면 다음과 같은 결과를 얻을
수 있다.

3. 관계 기반 알고리즘 251

정보과학-3단원-2차.indd 251 2021-12-20 오전 9:47:30


해보기 2 분할정복 알고리즘의 시간 복잡도 분석

프로그램
01 #include <stdio.h >
02 int count;
얼마나 많은 중복 계산이
03
발생할까?
04 int f(int n)
05 {
06 count ++;
07 if(n == 1 || n == 2)
08 return 1;
09 else
10 return f(n - 1) + f(n - 2);
11 }
12
13 int main( )
텍스트 파일(out.txt) 내부 14 {
의 데이터를 그래프를 나 15 FILE *fp = fopen("out.txt", "w");
타낼 수 있는 응용 프로그
16 int n;
램을 이용하여 시각화하
면 어떻게 될까?
17 for(n = 1; n <= 40; n ++)
18 {
19 count = 0;
20 fprintf(fp, "%d %d %d\n", n, count, f(n));
21 }
22 fclose(fp);
23 }

▲▲중복 계산에 따른 재귀 호출 횟수 분석

1 4 7 10 13 16 19 22 25 28 31 34 37 40
시각화를 통해 분석한 결과 중복 계산의 발생이 분할정복 알고리즘의 시간 복잡도를
O(2n)까지 증가시킨 것을 알 수 있다. 따라서 n이 커지면 커질수록 수행 시간이 기하급수
적으로 증가하게 된 것이다. 따라서 컴퓨터를 이용하더라도 합리적인 시간 내에 해를 얻
을 수 없는 상황이 발생한다.
이러한 문제를 해결하기 위해 하향식 동적 계획법, 즉 메모이제이션 알고리즘을 적용해

252 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 252 2021-12-20 오전 9:47:30


보자. 이를 위해서는 재귀 함수의 실행 과정에서 호출된 작은 문제의 계산 결과를 기록해
야 한다. 다음과 같이 배열을 이용하여 기록할 수 있다.

[메모이제이션을 적용한 피보나치수열 문제의 알고리즘]


for i ← 1 to n step 1
memo[i] ← 0
end for

f(n)
if memo[n] ≠ 0
f(n) ← memo[n]
else if n = 1 or n = 2
memo[n] ← 1
f(n) ← memo[n]
else
memo[n] ← f(n - 1) + f(n - 2)
f(n) ← memo[n]
end if
end f

먼저 계산 결과의 기록을 위한 배열 memo[ ]를 선언하고, 모두 0으로 초기화한다. 그리


고 f (k)가 호출되어 계산이 완료될 때마다 그 결과를 memo[k]에도 함께 저장한다. 따라
서 memo[k]의 값이 0이 아니라면, f (k)는 이미 계산된 문제라고 할 수 있다. 이때 f (k)는 분할정복과 동적 계획법
분할정복 알고리즘으로 문제
분할을 통한 재귀 호출을 멈추고, 이미 기록되어 있는 memo[k]의 값을 반환하면 된다. 를 해결하기에 적합하지 않은

다음은 이를 프로그래밍을 통해 구현한 예시 코드이다. 문제들에 대해서 활용할 수 있


는 방법이 바로 동적 계획법이
다. 동적 계획법은 문제의 분해
과정에서 부분 문제의 중복이
해보기 3 하향식 동적 계획법을 적용한 피보나치수열 문제
발생할 때 활용할 수 있는 매
프로그램 우 효율적인 알고리즘 설계 방
법이다.
01 #include <stdio.h >
02 long long memo[100000]; Tip
03 오버플로 문제를 방지하기 위해
04 long long f(int n) 자료형을 long long형으로 바
꾸었다.
05 {
06 if(memo[n] ! = 0) return memo[n];
07 else if(n == 1 || n == 2)
08 return memo[n] = 1;
09 else
10 return memo[n] = f(n - 1) + f(n - 2);
11 }
12
13 int main( )

3. 관계 기반 알고리즘 253

정보과학-3단원-2차.indd 253 2021-12-20 오전 9:47:30


14 {
15 int n;
16 scanf("%d", &n);
17 printf("%lld\n", f(n));
18 }

위 프로그램을 실행하고 비교적 큰 값을 n으로 입력해 보면, 하향식 동적 계획법을 적용


하는 과정이 크게 복잡하지 않은데 반해, 효율의 향상은 매우 큰 것을 알 수 있을 것이다.
다음은 알고리즘의 효율을 분석하기 위해 작성한 프로그램과 그 결과이다.

해보기 4 하향식 동적 계획법 알고리즘의 시간 복잡도 분석

프로그램
01 #include <stdio.h >
02 long long count, memo[100000];
03
04 long long f(int n)
05 {
06 count ++;
07 if(memo[n] ! = 0)
08 return memo[n];
09 else if(n == 1 || n == 2)
10 return memo[n] = 1;
11 else
12 return memo[n] = f(n - 1) + f(n - 2);
13
14 }
15
16 int main( )
17 {
18 FILE *fp = fopen("out.txt", "w");
19 int n, m;
Tip 20
n값이 바뀌면 배열 memo[ ]의 21 for(n = 1; n <= 100; n ++)
값을 모두 초기화해야 한다. 22 {
23 for(m = 1; m < n; m ++)
24 memo[m] = 0;
25
26 count = 0;
27 fprintf(fp, "%d %lld %lld\n", n, count, f(n));
28 }
29

254 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 254 2021-12-20 오전 9:47:30


30 fclose(fp);
31 }

200
180
160
140
120
100
80
60
40
20
0
1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96
▲▲하향식 동적 계획법을 적용한 후의 재귀 호출 횟수 분석

시각화를 통해 분석한 결과 하향식 동적 계획법을 통해 설계한 알고리즘의 시간 복잡도


가 O(n)으로 나타나는 것을 확인할 수 있다. 순수한 분할정복 알고리즘의 시간 복잡도가
O(kn)이었던 것을 감안했을 때 엄청난 효율의 향상을 가져온 것이다. 이것이 하향식 동적
계획법, 즉 메모이제이션을 사용하는 이유이다.

03
탐구 활동

다음과 같은 2가지 종류의 블록이 있다.

이 블록들을 여러 개 사용하여 가로 2칸, 세로 2칸 크기의 판을 채우는 방법은 다음 3가


지이다. 이때, 블록들을 회전해서 채워 넣는 것도 가능하다.

자연수 n에 대하여 가로 2칸, 세로 n칸 크기의 판을 채우는 모든 방법의 수를 구해 보자.

❶ 다음의 함수 정의를 이용하여 점화식을 설계해 보자.

f (n)은 가로 2칸, 세로 n칸을 채우는 모든 방법의 수

3. 관계 기반 알고리즘 255

정보과학-3단원-2차.indd 255 2021-12-20 오전 9:47:31


❷ 분할정복을 이용한 알고리즘을 설계해 보자.

❸ 분할정복 알고리즘을 프로그래밍을 통해 구현하고, 시간 복잡도를 분석해 보자.

❹ 하향식 동적 계획법을 적용한 알고리즘을 설계해 보자.

❺ 하향식 동적 계획법을 적용한 알고리즘의 효율을 분석해 보자.

3 상향식 동적 계획법
상향식 동적 계획법은 재귀 함수를 이용하지 않고, 분할정복 및 메모이제이션 알고리즘을
모두 적용할 수 있는 알고리즘 설계 방법이다. 따라서 메모이제이션을 사용할 때의 계산 효
율은 유지하면서도, 함수의 재귀 호출 과정에서 발생하는 시간의 낭비를 막을 수 있다.
상향식 동적 계획법은 분할정복이나 하향식 동적 계획법과 마찬가지로 전체 문제와 부

256 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 256 2021-12-20 오전 9:47:31


분 문제 간의 재귀적 관계를 이용하는 방식이다. 따라서 상향식 동적 계획법을 적용하기
위해서는 점화식을 설계해야 한다.
앞서 피보나치수열의 n번째 항을 구하는 문제의 경우에 다음과 같은 점화식을 설계하였
다. 이것은 상향식 동적 계획법을 적용하는 과정에서도 변함없이 활용된다.
(n = 1, 2)
{ f (n -1)+f (n -2) (n ≥3)
1
f (n)=

그런데 분할정복 방법을 적용한 알고리즘을 설계할 때는 재귀 함수를 바탕으로 알고리


즘을 설계하였으며, 따라서 문제의 분할 및 정복 구조가 큰 문제에서 작은 문제로 향하는
하향식 구조였다. 이에 반해 상향식 동적 계획법을 이용할 때는 재귀 함수 대신 반복문을
이용하므로 다음과 같은 알고리즘을 생각할 수 있다.

[피보나치수열의 n번째 항을 구하는 상향식 동적 계획법 알고리즘]


for i ← 1 to n step 1
if i = 1
dt[i] ← 1
else if i = 2 Tip
dt[i] ← 1 dt는 동적 테이블(dynamic table)

else 의 의미로 사용되었다.

dt[i] ← dt[i - 1] + dt[i - 2]


end if
end for
print dt[n]

이와 같은 알고리즘의 진행 과정은 가장 작은 문제에서 큰 문제로 향하는 상향식 구조


임을 알 수 있다. 또한 계산 여부를 확인하기 위해 별도의 기록을 하는 것이 아니라, 다음
으로 큰 문제를 계산하기 위해 이전 문제들을 정복한 결과물을 기록한다는 점에서 하향식
동적 계획법과는 다소 차이가 있다. 따라서 알고리즘의 설계 및 구현이 더욱 간단해지는
장점을 갖는다.

해보기 5 상향식 동적 계획법을 적용한 피보나치수열 문제 1

프로그램
01 #include <stdio.h >
02 long long dt[100000];
03
04 int main( )
05 {
06 int n, i;

3. 관계 기반 알고리즘 257

정보과학-3단원-2차.indd 257 2021-12-20 오전 9:47:31


07 scanf("%d", &n);
08
09 for(i = 1; i <= n; i ++)
10 {
11 if(i == 1 || i == 2) dt[i] = 1;
12 else dt[i] = dt[i - 1] +dt[i - 2];
13 }
14
15 printf("%lld\n", dt[n]);
16 }

상향식 동적 계획법을 적용하면 재귀 함수를 이용하는 하향식 설계와는 달리 중복 계산


의 여지가 없다. 따라서 피보나치수열 문제를 해결하는 알고리즘의 시간 복잡도는 O(n)으
로 동일하다. 또한 함수의 호출과 반환 과정에서 발생하는 시간 소모가 사실상 없다고 할
수 있으므로 하향식 설계에 비해 수행 시간이 더 짧은 장점을 갖는다.
동적 계획법을 적용하기 위해서는 추가적인 메모리 사용이 발생하는데, 이는 입력값의
크기에 비례하게 된다. 그러나 상향식 동적 계획법을 이용하면 이러한 문제점을 크게 해
소할 수 있다. 이전의 결과를 알아야만 다음 문제를 해결할 수 있기 때문에 추가적인 메모
리를 사용하지만, 다음 문제를 해결하기 위해 반드시 필요한 이전 결과만 저장해도 된다
는 점에서 차이가 발생한다.
다음은 추가되는 메모리 공간의 크기를 줄이기 위해서 알고리즘을 개선한 것이다. 본래
의 알고리즘이 n개의 배열 공간을 이용하는 대신 개선된 알고리즘에서는 반드시 필요한
공간 3개만을 활용하였다.

[메모리 낭비를 막기 위해 개선된 상향식 동적 계획법 알고리즘]


for i ← 1 to n step 1
if i = 1
d1 ← 1
else if i = 2
d2 ← 1
else
d3 ← dt1 + dt2
d1 ← dt2
d2 ← d3
end if
end for
print d3

258 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 258 2021-12-20 오전 9:47:31


다음은 이를 프로그래밍을 통해 구현한 것이다. 알고리즘의 공간 복잡도가 O(n)에서
O(1)로 향상된 것을 알 수 있다.

해보기 6 상향식 동적 계획법을 적용한 피보나치수열 문제 2

프로그램
01 #include <stdio.h >
02
03 int main( )
04 {
05 long long d1 = 1, d2 = 1, d3;
06 int n, i;
07 scanf("%d", &n);
08
09 for(i = 3; i <= n; i ++)
10 {
11 d3 = d2 + d1;
12 d1 = d2;
13 d2 = d3;
14 }
15
16 printf("%lld\n", d3);
17 }

04
탐구 활동

100의 모든 약수의 합을 구하는 문제가 있다. 이 문제를 해결하는 분할정복 알고리즘을


설계하고 프로그래밍을 통해 구현해 보자.

❶ 점화식을 바탕으로 상향식 동적 계획법 알고리즘을 설계해 보자.

❷ ‌상향식 동적 계획법 알고리즘을 프로그래밍을 통해 구현하고, 알고리즘의 시간 복잡도 및


공간 복잡도를 분석해 보자.

3. 관계 기반 알고리즘 259

정보과학-3단원-2차.indd 259 2021-12-20 오전 9:47:31


05
탐구 활동

◯◯ 나라에서 사용하는 동전은 10원, 50원, 60원, 500원으로 구성되어 있다. 입력받은
금액 n원을 동전으로만 거슬러 주기 위해 필요한 최소 동전의 개수를 구해 보자.(단, n원
은 10원 단위로 입력해야 한다.)

❶ 함수, 최소 문제 및 관계식의 정의를 바탕으로 점화식을 설계해 보자.

❷ 상향식 동적 계획법 알고리즘을 설계해 보자.

❸ 알고리즘을 프로그래밍을 통해 구현하고, 문제의 해를 구해 보자.

정리
하기 •전체 문제와 부분 문제의 재귀적 관계를 바탕으로 분할정복 알고리즘을 설계할 수 있다.
•분할정복 알고리즘은 중복 계산의 문제가 발생할 수 있다.
•동적 계획법은 동적 테이블을 이용하여 이전 문제의 계산 결과를 기록하는 방식으로 설계한다.
•‌하향식 동적 계획법은 분할정복 알고리즘의 중복 계산 문제를 해결하기 위해 이전의 계산 여부를 기록하는 알고
리즘 설계 방법이다.
•‌상향식 동적 계획법은 반복문과 추가 메모리의 활용을 통해 시간 복잡도와 공간 복잡도를 향상시키는 효율적인
알고리즘 설계 방법이다.

260 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 260 2021-12-20 오전 9:47:31


읽기 인간 게놈 프로젝트(Human-Genome project) 연구
자료

인간 게놈 프로젝트는 인간이 가지고 있는 게놈의 모든 염기 서열을 해석하기 위한 프로젝트로, 1990년에 시작되어


2003년에 완료되었다. 이 프로젝트는 1990년에 미국 에너지부(DOE: Department of Energy)와 국립보건원(NIH:
the National Institutes of Health)에서 30억 달러 정도의 예산을 가지고 발족시켰다. 본래 15년 계획으로 잡혀 있
었지만, 그동안 생물학과 정보학이 이론적·기술적으로 발전하면서 실제로는 예정보다 2년 정도 빠른 2000년에 게놈
의 기본 드래프트가 완성되었으며, 같은 해 6
월 26일에 빌 클린턴 전 미국 대통령과 토니
블레어 전 영국 총리에 의해 발표되었다. 이
후 지속적인 작업이 수행되어 2003년 4월 14
일에 완성된 드래프트가 공개되었으며, 여기
에는 인간이 가진 모든 유전자 중 99%의 서열
(sequence)이 99.99%의 정확도로 포함되어
있었다.

현재, 인간 게놈 프로젝트로 밝혀진 바에


▲▲ DNA 염기 서열의 일부를 컴퓨터로 출력한 결과
따르면 인간 유전자는 모두 약 20000개에서
25000개 정도가 있다고 하며, 이 수는 과학자들이 예상한 것보다 상당히 적은 수이다. 이 프로젝트의 또 하나의 목표
는 빠르고 효율적인 DNA 서열화 방법을 개발하여 산업화하는 것이라 할 수 있으며, 이는 어느 정도 실현되었다. 그러
나 이런 방식으로 프로젝트 목표가 달성되더라도, 단순히 DNA 서열만 가지고 만든 데이터베이스만으로는 이용 가치
가 없기 때문에 이를 해석해서 이용할 수 있는 컴퓨터 프로그램, 즉 어노테이션(annotation)의 개발이 필요하며, 이는
생명정보학(bioinformatics)의 가장 일반적인 작업이다. 기본적으로 이러한 어노테이션은 생물학 연구자가 하나하나
찾아내어 가야 하지만, 게놈 프로젝트와 같이 대량의 정보 처리가 필요한 상황에서는 컴퓨터를 이용한 빠른 처리가 필
요해지기 때문에 현재 이러한 생물정보학적 방법론(Big Data Science)은 게놈 프로젝트에서 매우 중요한 부분을 담
당하고 있다.

DNA 서열화(sequencing) 알고리즘 중, 가장 대표적인 알고리즘은 1970년도에 솔 니들만(Saul B. Needleman)


과 크리스티안 분쉬(Christian D. Wunsch)에 의해 개발된 니 G C C C T A G C G
들만-분쉬 알고리즘이다. 이 알고리즘은 정보과학의 문제 해 0 0 0 0 0 0 0 0 0 0
결 기법 중 하나인 동적 계획법을 생명정보학에 응용한 첫 번 G 0 1 1 1 1 1 1 1 1 1

째 사례로, 공통 부모를 가진 두 자식의 염기 서열 간의 유사 패 C 0 1 2 2 2 2 2 2 2 2

턴을 분석하는 기능을 수행한다. 예를 들어, 공통 부모를 가진 G 0 1 2 2 2 2 2 3 3 3

자식 A의 염기 서열이 “ATGCCC”이고 자식 B의 염기 서열이 C 0 1 2 3 3 3 3 3 4 4


A 0 1 2 3 3 3 4 4 4 4
“AGGTCG”라고 할 때, 자식 A에 대한 자식 B의 공통 염기 서
A 0 1 2 3 3 3 4 4 4 4
열은 “A­G­C­”임을 밝혀내고, 다른 염기 서열에도 이 과정을 반복
T 0 1 2 3 3 4 4 4 4 4
적으로 진행함으로써 모든 인간의 공통 염기 서열, 즉 게놈 프
G 0 1 2 3 3 4 4 5 5 5
로젝트의 기초 연구를 완료한 것이다.
▲▲니들만 - 분쉬 서열화 알고리즘의 수행 과정

3. 관계 기반 알고리즘 261

정보과학-3단원-2차.indd 261 2021-12-20 오전 9:47:32


프로젝트 수행하기

니들만-분쉬 알고리즘은 두 개의 염기 서열을 x축과 y축의 이름으로 배치한 후 생성되는 2차원 테이블에 대한
초기화, 점수 계산, 되추적의 3가지 과정으로 구현될 수 있다. 초기화는 생성한 테이블의 1행과 1열 전체를 0으
로 정하는 작업이며, 점수 계산은 다음과 같은 알고리즘을 거친다. 단, 여기에서 MAX[A,B,C]는 A,B,C 중 최
댓값을 의미한다. 다음은 이 과정을 자연어로 기술하고 도식화한 것이다.

❶ x축과 y축의 염기를 비교하여,


① -1. 염기가 동일하면, MAX [왼쪽 대각선 위 + 2, 왼쪽 - 2, 위쪽 - 2]를 기록한다.
①-2 염기가 다르면, MAX [왼쪽 대각선 위 - 1, 왼쪽 - 2, 위쪽 - 2]를 기록한다.
❷ 기록한 값이 어느 셀에서 왔는지 화살표로 표시한다.
❸ 이 과정을 반복적으로 수행하여 모든 셀의 점수를 계산한다.

A G G T C G A G G T C G A G G T C G

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

A 0 A 0 2 A 0 2 0 -1 -1 -1 -1

T 0 T 0 T 0 0 1 -1 1 -1 -2

G 0 G 0 G 0 -1 2 3 1 0 1

C 0 C 0 C 0 -1 0 1 2 3 1

C 0 C 0 C 0 -1 -2 -1 0 4 2

C 0 C 0 C 0 -1 -2 -3 -2 2 3

▲▲초기화 ▲▲점수 계산 1 ▲▲점수 계산 완료

A G G T C G

0 0 0 0 0 0 0

A 0 2 0 -1 -1 -1 -1

T 0 0 1 -1 1 -1 -2 A G G T C G
| | |
G 0 -1 2 3 1 0 1
A T G C C C
C 0 -1 0 1 2 3 1

C 0 -1 -2 -1 0 4 2
∴ A -­G -­C -­
C 0 -1 -2 -3 -2 2 3

▲▲되추적 ▲▲공통 염기 서열

262 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 262 2021-12-20 오전 9:47:32


1 ‌과제 1 ‌1000개의 염기로 구성된 염기 서열 샘플 2개를 텍스트 파일(*.txt)로 랜덤 생성하는 프로그램을 작성
해 보자.

2 ‌과제 2 생성된 샘플 2개의 공통 염기 서열, 유사도(%) 및 알고리즘 수행 시간을 텍스트 파일(*.txt)로 출력하는
프로그램을 작성해 보자.

중단원 마무리 263

정보과학-3단원-2차.indd 263 2021-12-20 오전 9:47:32


대단원 마무리

문제의 개념
문제의 개념과 종류
계산, 결정, 계수, 최적화

문제와 알고리즘 알고리즘의 표현


알고리즘의 복잡도
알고리즘의 표현과 분석 시간 복잡도 계산
최악, 최선, 평균
점근 표기법

탐색 기반 알고리즘의 개념
탐색 기반 알고리즘 설계
탐색 기반 알고리즘 설계 방법

전체 탐색 알고리즘 설계 방법

알고리즘 탐색 기반 알고리즘 전체 탐색 선형 전체 탐색
비선형 전체 탐색

탐색 공간의 배제란?
탐색 공간의 배제 탐욕 알고리즘 설계 방법
분기한정 알고리즘 설계 방법

문제 분해와 관계
관계 기반 알고리즘 설계
재귀적 관계와 점화식
관계 기반 알고리즘
관계식을 이용한 알고리즘 설계
동적 계획법 하향식 동적 계획법
상향식 동적 계획법

1문 ‌ 제의 개념과 종류 정보과학에서 다루어지는 문제들은 크게 계산 문제, 결정 문제, 계수 문제, 최적화 문제로 나눌 수 있다.
2 알고리즘의
‌ 표현과 분석 알고리즘은 다양한 형태로 표현될 수 있으며, 명확하게 표현하는 것이 중요하다. 또한 알고리즘의 성능은 계산 문제의
해결에 필요한 수행 시간 및 사용 공간의 관점에서 분석이 가능하며, 특히 수행 시간의 관점에서 입력 크기에 따른 최악, 평균, 최선의 경우의 수
행 시간을 근사적으로 나타낸 것을 시간 복잡도의 점근 표기법이라고 한다.

3 탐색
‌ 기반 알고리즘 설계 탐색 기반 알고리즘은 가능한 경우들에 대해 탐색해 원하는 결과를 얻어 내는 방법이다. 또한 탐색 공간의 일부를
배제함으로써 탐색의 효율을 높이는 알고리즘을 설계할 수 있다.

4 전체
‌ 탐색 전체 탐색은 해가 존재할 수 있는 탐색 공간 전체를 탐색하면서 원하는 해를 찾아가는 방법이다. 탐색 공간의 형태에 따라 선형
전체 탐색과 비선형 전체 탐색으로 구분한다.

5 탐색
‌ 공간의 배제 탐색해야 할 문제 공간의 크기를 줄임으로써 알고리즘의 효율을 높이기 위해 탐욕 기법, 분기한정 기법을 사용할 수 있다.
6 관계
‌ 기반 알고리즘 설계 관계란 전체 문제와 부분 문제 간의 결합 구조를 뜻하며, 주어진 문제와 그것의 부분 문제 간의 관계를 재귀적으로
정의할 수 있다면 분할정복 알고리즘을 통해 문제를 해결할 수 있다.

7 동적
‌ 계획법 분할정복 알고리즘의 계산 중복 문제를 해결하기 위해 계산 여부를 확인하는 방식의 하향식 동적 계획법을 설계할 수 있다. 또
한 동적 계획법의 진행 방향을 상향식으로 설계하면 재귀 호출에 따른 시간 소모를 줄일 수 있다.

264 Ⅲ. 알고리즘

정보과학-3단원-2차.indd 264 2021-12-20 오전 9:47:33


대단원 평가 문제

01 다음 프로그램을 보고 물음에 답해 보자. 02 다‌ 음 프로그램은 기둥 A에 있는 n개의 원판을 주어진 2가


지 규칙을 지키면서 기둥 C로 최소 횟수로 옮기는 방법을
01 #include <stdio.h >
출력하는 프로그램이다. 다음 물음에 답해 보자.
02 int f(int n)
03 { 규칙 1 한 번에 기둥의 가장 위에 있는 원판을 하나씩만 옮길 수 있다.
04 int s = 0; 규칙 2 작은 원판 위에 큰 원판을 올릴 수 없다.
05 for(int i = 1 ; i <= n ; i ++ )
06 s + = i; 01 #include <stdio.h >
07 return s; 02 void f(int n, char s, char m, char e)
08 } 03 {
09 int g(int n) 04 if(n > 0)
10 { 05 {
11 int s = 0; 06 f(n - 1, s, e, m);
12 for(int i = n, j = 1 ; i > = 1 ; i >> = 1, j <<= 1) 07 printf("%d: %c -> %c\n", n, s, e);
13 s + = ((i + 1) / 2) * ((i + 1) / 2) * j; 08 f(n - 1, m, s, e);
14 return s; 09 }
15 } 10 }
16 int main( ) 11
17 { 12 int main( )
18 int n; 13 {
19 scanf("%d", &n); 14 int n;
20 printf("%d %d\n", f(n), g(n)); 15 scanf("%d", &n);
21 return 0; 16 f(n, 'A', 'B', 'C');
22 } 17 }

① 입력값이 10일 때, 출력 결과를 적어 보자. ① 입력값이 2일 때, 출력 결과를 적어 보자.

② ‌입력값 n에 대해서 f( ), g( )의 시간 복잡도를 빅오 표기법으 ② ‌다음과 같은 규칙을 새롭게 추가하고자 한다. 이를 해결하기 위

로 나타내 보자. 해서 알고리즘 f( )를 재작성해 보자.

규칙 3 원판을 옮길 때 반드시 인접한 기둥으로만 옮길 수 있다.

대단원 평가 문제 265

정보과학-3단원-2차.indd 265 2021-12-20 오전 9:47:33

You might also like