1. 시간 복잡도


1.1 분석 종류


  • $T(n)$: Every-case analysis
    • 입력크기(input size)에만 종속
    • 입력값과는 무관하게 결과값은 항상 일정

 

  • $W(n)$: Worst-case analysis
    • 입력크기와 입력값 모두에 종속
    • 단위연산이 수행되는 횟수가 최대인 경우 선택

 

  • $A(n)$: Average-case analysis
    • 입력크기와 입력값 모두에 종속
    • 모든 입력에 대해 단위연산이 수행되는 기대치(평균)
    • 각 입력에 대해서 확률 할당 가능

 

  • $B(n)$: Best-case analysis
    • 입력크기와 입력값 모두에 종속
    • 단위연산이 수행되는 횟수가 최소인 경우 선택

 

1.2 시간 복잡도 정의


  • Big-O

모든 $n$, $n \geq n_0$에 대해 $f(n) \le c\times g(n)$인 조건을 만족시키는 두 양의 상수 $c$와 $n_0$가 존재하기만 하면 $f(n)=O(g(n))$이다.

 

예를 들면 $O(n)$: 최악의 경우 $n$번까지 수행되면 프로그램을 끝낼 수 있다.

 

  • Big-Omega

모든 $n$, $n \geq n_0$에 대해 $f(n) \geq c\times g(n)$인 조건을 만족시키는 두 양의 상수 $c$와 $n_0$가 존재하기만 하면 $f(n)=\Omega(g(n))$이다.

 

예를 들면 $O(n)$: 최소 $n$번은 수행되어야 프로그램을 끝낼 수 있다.

 

  • Theta

모든 $n$, $n \geq n_0$에 대해 $c_1\times g(n) \le f(n) \le c_2\times g(n)$인 조건을 만족시키는 세 양의 상수 $c_1, c_2, n_0$가 존재하기만 하면 $f(n)=\theta(g(n))$이다.

 

Theta의 경우 $O와\ \Omega$의 교집합이다. 즉, 차수가 같은 문제이다.

 

  • Small-O

모든 $n$, $n \geq n_0$에 대해 $0 \leq f(n) \lt c \times g(n)$인 조건을 만족시키는 두 양의 상수 $c, n_0$가 존재하기만 하면 $f(n)=O(g(n))$이다.

 

예를 들면 $O(n)$: 최악의 경우에도 n번 미만으로 수행되면 프로그램은 끝낼 수 있다.

 

$\lim_{x \to \infty}$ $f(x)\over g(x)$ $=0$로 나타낼 수 있다.

 

Small-O와 Big-O의 차이점은 다음과 같다.

- Big-O는 실수 $c>0$ 중에서 하나만 성립해도 된다.

- Small-O는 모든 실수 $c>0$에 대해서 성립해야 한다.

- Small-O는 Big-O에서 등호를 뺀다.

 

추가적으로 Small-omega($\omega$)도 존재한다.

 

1.3 시간복잡도 정의를 이용하여 다음 4개의 문제에 대하 statement의 참, 거짓을 판별하시오 (시간복잡도 계산 문제)


 

1.4 $8n^2 + \sqrt2 = O(n^2)$임을 보여라.


모든 $n, n \geq n_0$에 대하여 $f(n) \leq c \times g(n)$인 조건을 만족시키는 두 양의 상수 $c$와 $n_0$가 존재하기만하면 $f(n) = O(g(n))$이다.

 

1. $f(n) = 8n^2 + \sqrt2$

2. $g(n) = n^2$

3. 대입 => $8n^2 + \sqrt2 \leq c \times n^2$

4. $\sqrt2$는 약 1.414

5. $8n^2 + 1.414 \leq c \times n^2$

6. n = 2라 가정하면

7. $32 + 1.414 \leq c \times 4$

8. $33.414 \leq c \times 4$

9. $c \geq 9$

 

1.5 Big-O, Omega, Theta, small-o의 정의를 이용하여 $5x^3 + 4x^2 + 6x \in \Theta(n^3)$ 임을 보이시오.


1. $g(x) = x^3$

2. $g_2(x) = 6x^3$

3. $x^3 \leq 5x^3+4x^2+6x \leq 6x^3$

 

2. 프림, 크루스칼, 다익스트라


2.1 비방향 그래프를 보고 크루스칼 알고리즘을 이용하여 최소 비용 신장 트리를 구하는 과정을 단계별로 보이시오


  • 크루스칼 알고리즘의 핵심
    • 오름차순
      1. 가중치를 기준으로 간선을 오름차순 정렬
      2. 낮은 가중치의 간선부터 시작해서 하나씩 그래프에 추가
      3. 사이클을 형성하는 간선을 추가하지 않음
      4. 간선의 수가 정점의 수보다 하나 적을 때 MST가 완성
    • 내림차순
      1. 가중치를 기준으로 간선을 내림차순으로 정렬
      2. 높은 가중치의 간선부터 시작해서 하나씩 그래프에서 제거
      3. 두 정점을 연결하는 다른 경로가 없을 경우 해당 간선은 제거하지 않음
      4. 간선의 수가 정점의 수보다 하나 적을 때 MST가 완성

 

 

2.2 그래프를 보고 다익스트라 알고리즘을 이용하여 v6를 출발점으로하는 최단 거리를 구하는 과정을 단계별로 보이시오


  • 간선의 가중치를 오름차순으로 정렬한다.
  • 가중치가 낮은 순서대로 간선을 하나씩 그래프에 추가한다.
  • 그래프 내에서 사이클을 형성하는 간선은 추가하지 않는다.
  • 간선의 개수가 정점의 개수보다 '1' 작으면 끝낸다.

 

3. NP, NP-complete


3.1 NP, NP-hard, NP-complete의 정의


  • $P$ : 어떤 문제가 주어졌을 때 다항식으로 표현되어 polynomical time 즉, 다항 시간내에 해결 가능한 알고리즘을 의미하며 알고리즘의 복잡도가 $O(n^k)$로 표현되는 문제를 '$P$'라 한다. (복잡도 $O(n^k)$ 이하를 가지는 경우 같은 복잡도 내에 모든 해를 구한다.)

 

  • $NP$ : 어떤 문제가 주어졌을 때 다항식으로 표현될 수 있는지의 여부가 결정되지 않은 문제들을 'NP(Non-deterministic polynomial)'라 한다.

 

  • $NP-Complete$ : NP이면서 동시에 NP-Hard 에 속한다면 그 문제는 'NP-Complete'라 한다. (전수조사가 답)

 

  • $NP-Hard$ : 적어도 모든 NP 문제만큼은 어려운 문제들의 집합이며, 만약 P-NP 문제가 P=NP로 풀린다면 P=NP=NP-Complete이므로 P와 NP는 NP-Hard의 부분집합이 되고, P≠NP인 경우는 P와 NP-Hard는 서로소가 된다. *다항시간 : $T(n) = O(n^k), k$ 는 상수  => $k$가 상수로 고정이 된다면 그 문제는 해결하기 쉬운 문제. 다항시간안에 풀 수 있는 문제이므로.

3.2 해밀턴회로 거리 구하기(그래프가 주어질 때 그래프의 모든 점을 정확하게 한번씩만 지나는 경로가 존재하는가?) (NP-hard)


 

4. 배열 제시 후 소팅 알고리즘을 사용하여 정렬 과정을 보여라


 

4.1 Merge sort 알고리즘을 사용하여 8개의 숫자를 정렬하는 과정을 보여라


 

병합 정렬의 예

 

 

4.2 각종 정렬 기법들의 장단점과 시간복잡도


 

5. Divide and Conquer 알고리즘과 Dynamic Programming 알고리즘 차이


 

5.1 분할 정복법이 비효율적인 경우를 설명하라


 

 

5.2 분할 정복법과 동적프로그래밍을 이용하여 이항계수를 구하는 알고리즘 작성 후 두방식의 차이점에 대해 적으시오


  • 분할 정복법(Divide and Conquer)
    • 어떠한 큰 문제를 해결하기 위해 큰 문제를 작은 단위의 문제로 나누어 해결하는 방법 (Top-down)
    • 문제의 크기가 충분히 작아질때까지 반복적으로 분할
    • 해결한 작은 문제를 가지고 바로 윗 단계의 문제를 해결해 나가는 방식
    • 대표적인 예로는 Binary Search와 Merge Sort, Quick Sort 등이 있다.

 

  • 동적 프로그래밍(Dynamic Programming)
    • 문제를 작은 인스턴스들로 나누고 Bottom-up 순서로 풀어나가면서 문제의 값을 정해놓고 필요할 때 가져와  문제를 해결하는 방식이다. "기억하며 풀기"라 생각하면 된다.
    • 대표적인 예로는 TSP 문제, 피보나치 수열, 파스칼의 트리 작성 등이 있다.

 

분할정복법과 동적 프로그래밍의 공통점과 차이점

  • 공통점 : 문제를 작은 단위로 나누어 해결
  • 차이점 : 분할정복법은 Top-down 방식이며, 동적 프로그래밍은 Bottom-up 방식이다.

 

5.3 Binomial coefficient를 계산하려할 때 다음을 구해라


  • Divide-and-Conquer 방법을 사용하는 pseudo code 작성
  • Dynamic Programming 방법을 사용하는 pseudo code 작성
  • 위 두 접근 방법의 차이점을 서술

 

5.4 이항계수 수학적 귀납법으로 증명하고, 동적 프로그래밍으로 알고리즘을 구현하라.


bottom-up 방식

int binomial(int n, int k) 
{
 for (int i=0; i<=n; i++) 
 {
     for (int j=0; j<=k && j<=i; j++) 
     {
         if (k==0 || n==k)
             arr[i][j] = 1;
         else
             arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
     }
 }
 return arr[n][k];
}

 

6. DFS(Depth First Search)와  BFS(Breadth First Search)의 차이


  • DFS, BFS의 의사코드를 작성하고 이들의 차이를 제시한 다음, 간단한 트리를 작성하여 순회하는 것을 보이시오.

 

8. 행렬을 주고 TSP에 관한 문제


 

 

9. Strassen 행렬 알고리즘을 사용하여 2*2 행렬 A,B의 곱 C를 구하라(m1,m2,...,m7)을 사용해야함


9.1 Strassen's Matrix Multiplication 알고리즘에 대해 설명하라


 

 

9.2 행렬 곱셉 알고리즘 + 쉬트라센 + 복잡도


아래와 같이 행렬 A,B가 있고 두 행렬의 곱이 행렬 C로 표현한다 가정한다.

 

$A = \left[ \begin{array}{cc|c} a_{11} & a_{12} \\\\ a_{21} & a_{22} \end{array} \right],\ $ $B= \left[ \begin{array}{cc|c} b_{11} & b_{12} \\\\ b_{21} & b_{22} \end{array} \right],\ $ $C=\left[ \begin{array}{cc|c} c_{11} & c_{12} \\\\ c_{21} & c_{22} \end{array} \right]$

 

이 때, $A_{ij},B_{ij},C_{ij} \in F^{2^n-1 \times 2^n-1}$ 이다.

 

따라서 일반적인 행렬의 곱은 다음과 같이 표현할 수 있으며, 총 8번의 곱셈과 4번의 덧셈으로 연산된다.

 

$C_{11} = A_{11}B_{11} + A_{12}B_{21}$ 
$C_{12} = A_{11}B_{12} + A_{12}B_{22}$ 
$C_{21} = A_{21}B_{11} + A_{22}B_{21}$ 
$C_{22} = A_{21}B_{12} + A_{22}B_{22}$

 

슈트라센 알고리즘은 행렬의 곱셉을 더하기 연산으로 풀어 각 원소를 구할 수 있는 $M$이라는 연산 행렬로 표현한다. 행렬 $M$은 7번의 곱셈과 10번의 덧셈으로 연산으로 나타낼 수 있으며 아래와 같이 표현한다.

 

$M_1 = (A_{11} + A_{22})(B_{11}+B_{22})$ 
$M_2 = (A_{21} + A_{22})B_{11}$ 
$M_3 = A_{11} (B_{12}-B_{22})$ 
$M_4 = A_{22}(B_{21}-B_{11})$ 
$M_5 = (A_{11} + A_{12})B_{22}$ 
$M_6 = (A_{21} - A_{11})(B_{11}+B_{12})$ 
$M_7 = (A_{12} - A_{22})(B_{21}+B_{22})$

 

최종적으로 행렬 C는 행렬 M의 더하기 연산으로 이루어져 있으며 각 원소에 해당하는 방법은 다음과 같다.

 

$C_{11} = M_1 + M_4 - M_5 + M_7$ 
$C_{12} = M_3 + M_5$ 
$C_{21} = M_2 + M_4$ 
$C_{22} = M_1 - M_2 + M_3 + M_6$

 

10. 5-Queen 문제를 백트래킹과 상태 설명 트리를 사용하여 해결하라


 

 

11. Floyd 알고리즘을 사용하여 W(=D0) 행렬과  D(=D) 행렬을 구하라. W, D를 구하는 과정을 서술하라


11.1 방향 그래프를 보고 플로이드 알고리즘을 이용하여 D와  P를 단계별로 적으시오.

 


 

 

12. 하노이의 탑 알고리즘을 써라


#include <stdio.h>

void HanoiTowerMove(int num, char from, char by, char to)
{
	if (num == 1)
		printf("원반 1을 %c에서 %c로 이동 \n", from, to);
	
	else
	{
		HanoiTowerMove(num - 1, from, to, by);
		printf("원반 %d를 %c에서 %c로 이동 \n", num, from, to);
		HanoiTowerMove(num - 1, by, from, to);
	}
}

int main(void)
{
	// 막대 A의 원반 5개를 막대 B를 경유하여 막대 C로 옮기기
	HanoiTowerMove(5, 'A', 'B', 'C');
	return 0;
}

 

13. 탐욕적 방법 Greedy Algorithm이 항상 최적의 해를 내지 못하는 경우의 예를 들라


Greedy Algorithm이 사용되는 대표적인 예제로는 "최소 수의 동전으로 거스름돈 거슬러주기" 문제가 있다. 

 

만약 우리가 마트의 캐셔로 일을 하고 있고, 850원을 거슬러 주어야 할 때 500원 동전 1개와 100원 동전 3개와 50원 동전 1개 총 4개의 동전을 건넴으로써 최소한의 동전을 거슬러 줄 수 있다. 하지만 이렇게 하지 않고 10원짜리 동전 85개를 건네주거나 50원짜리 17개를 건네주는 방법과 같이 다양한 경우의 수가 존재하며 이와 같을 경우 반드시 최적의 해를 내는 것은 아니다.

 

또한 우리나라의 경우 총 4개의 동전 500원, 100원, 50원, 10원이 있다. 하지만 만약 400원 동전이 발행된다면 400원 동전 2개, 50원 동전 1개를 통해 총 3개의 동전을 거슬러 줄 수 있을 것이다. 가장 최적의 방법이지만, 기존 알고리즘에 따르면 500원 1개, 100원 3개, 50원 1개로 거슬러주게 될 것이다. 이와 같이 탐욕 알고리즘은 항상 최적의 결과를 보장하지 못한다. 

 

Reference


[1] https://gmlwjd9405.github.io/2018/05/08/algorithm-merge-sort.html

[2] https://janghw.tistory.com/entry/알고리즘-Greedy-Algorithm-탐욕-알고리즘

 

정렬 알고리즘 복잡도


Sorting Algorithm 공간 복잡도 시간 복잡도
최선 최악 최선 평균 최악
Bubble Sort $O(1)$ $O(n)$ $O(n^2)$ $O(n^2)$ $O(n^2)$
Heap Sort $O(1)$ $O(n\times log\ n)$ $O(N\times log\ n)$ $O(n\times log\ n)$ $O(n\times log\ n)$
Insertion Sort $O(1)$ $O(n)$ $O(n)$ $O(n^2)$ $O(n^2)$
Merge Sort $O(1)$ $O(n\times log\ n)$ $O(n\times log\ n)$ $O(n\times log\ n)$ $O(n\times log\ n)$
Quick Sort $O(log \ n)$ $O(n\times log\ n)$ $O(n\times log\ n)$ $O(n\times log\ n)$ $O(n^2)$
Selection Sort $O(1)$ $O(n^2)$ $O(n^2)$ $O(n^2)$ $O(n^2)$
Shell Sort $O(1)$ $O(n)$      

 

정렬 알고리즘 특징 및 장단점


  • 버블 정렬
    • 장점 : 인접한 값만 계속해서 비교하는 방식으로 구현이 쉬우며, 코드가 직관적이다. n개 원소에 대해 n개의 메모리를 사용하기에 데이터를 하나씩 정밀 비교가 가능하다.
    • 단점 : 최선이든 최악이든 $O(N^2)$이라는 시간복잡도를 가진다. n개 원소에 대해 n개의 메모리를 사용하기에 원소의 개수가 많아지면 비교 횟수가 많아져 성능이 저하된다.

 

  • 힙 정렬 
    • 장점 : 추가적인 메모리를 필요로하지 않으면서 항상 $O(N\times logN)$의 시간 복잡도를 가진다. $O(N\times logN)$인 정렬 방법 중 가장 효율적인 정렬방법이라 할 수 있다. 퀵 정렬의 경우 효율적이나 최악의 경우 시간이 오래걸린다는 단점이 있으나 힙 정렬의 경우 항상 $O(N\times logN)$이 보장된다.
    • 단점 : 이상적인 경우에 퀵정렬과 비교했을 때 똑같이 $O(N\times logN)$이 나오긴 하나 실제 시간을 측정하면 퀵정렬보다 느리다고 한다. 즉, 데이터의 상태에 따라서 다른 정렬들에 비해서 조금 느린편이다. 또한, 안정성을 보장받지 못한다.

 

  • 선택 정렬
    • 장점 : 정렬을 위한 비교 횟수는 많으나 교환 횟수가 적기에, 교환이 많이 이루어져야 하는 상태에서 효율적으로 사용될 수 있으며, 이에 가장 적합한 자료상태는 역순 정렬이다. 즉, 내림차순이 정렬되어 있는 자료를 오름차순으로 재졍렬할 때 적합하다. 
    • 단점 : 정렬을 위한 비교 횟수가 많으며, 이미 정렬된 상태에서 소수의 자료가 추가되면 재정렬할 때 최악의 처리 속도를 보인다.

 

  • 빠른 정렬
    • 장점 : 기준값(Pivot)에 의한 분할을 통해 구현하는 정렬 방법으로, 분할 과정에서 $logN$이라는 시간이 소요되며, 전체적으로 $N\times logN$으로 준수한 편이다.
    • 단점 : 기존값에 따라 시간복잡도가 크게 달라진다(안정성이 없다). 기준값을 이상적인 값으로 선택했다면 $N\times logN$의 시간복잡도를 가지지만, 최악의 기준값을 선택할 경우 $O(N^2)$라는 시간복잡도를 갖게 된다.

 

  • 삽입 정렬
    • 장점 : 최선의 경우 $O(N)$이라는 빠른 효율성을 가지고 있다. 버블정렬의 비교횟수를 줄이기 위해 고안된 정렬이다. 버블정렬의 경우 비교대상의 메모리 값이 정렬되어 있더라도 비교연산을 진행하나, 삽입정렬은 버블정렬의 비교횟수를 줄이고 크기가 적은 데이터 집합을 정렬하는 알고리즘을 작성할 때 효율이 좋다.
    • 단점 : 최악의 경우 $O(N^2)$이라는 시간복잡도를 가지게 된다. 즉, 데이터의 상태와 크기에 따라 성능의 편차가 큰 정렬 방법이다.

 

  • 병합 정렬
    • 장점 : 퀵 정렬과 비슷하게 원본 배열을 절반씩 분할해가면서 정렬하는 정렬법으로써 분할하는 과정에서 $logN$ 만큼의 시간이 소요된다. 즉, 최종적으로 보게되면 $N\times logN$이 된다. 또한 퀵 정렬과 달리 기준값을 설정하는 과정없이 무조건 절반으로 분할하기에 기준값에 따라 성능이 달라지는 경우가 없다. 따라서 항상 $O(N\times logN)$이라는 시간복잡도를 가지게 된다.
    • 단점 : 병합정렬은 임시배열에 원본맵을 계속해서 옮겨주며 정렬을 하는 방식이기에 추가적인 메모리가 필요하다는 점이다. 데이터가 최악인 면을 고려하면 퀵 정렬보다는 병합정렬이 훨씬 빠르기 때문에 병합정렬을 사용하는 것이 많지만, 추가적인 메모리를 할당할 수 없다면 병합정렬을 사용할 수 없기 때문에 퀵을 사용해야 하는 것이다.

 

  • 쉘 정렬
    • 장점 : 삽입정렬의 단점을 보완하고 개념을 확대해서 만든 정렬방법으로, 삽입 정렬에 비해 성능이 우수하며, 어떤 데이터가 제 위치에서 멀리 떨어져있을 경우 여러 번의 교환이 발생하는 버블정렬의 단점을 해결한다.
    • 단점 : 일정한 간격에 따라 배열을 보아야 하며, 간격을 잘못 설정할 경우 성능이 급격히 저하될 수 있다.

 

  • 기수 정렬
    • 장점 : $O(N)$이라는 시간복잡도를 가지는 정렬방법으로 매우 빠른 속도를 가지고 있다.
    • 단점 : 버킷이라는 데이터 전체 크기와 기수 테이블의 크기만큼의 추가적인 메모리가 할당되어야 한다. 

 

  • 카운팅 정렬
    • 장점 : 비교를 하지 않고 정렬하는 방법으로 $O(N)$이라는 시간복잡도를 가지게 된다.
    • 단점 : 숫자 갯수를 저장해야 될 별도의 공간, 또 결과를 저장할 별도의 공간 등 추가적인 메모리가 필요하다.

 

정렬 알고리즘 장단점 요약


Sorting  장점 단점
버블 정렬 인접한 두 개의 데이터를 비교하기에 구현이 쉬우며 정밀 비교 가능 원소의 갯수가 많아지면 비교 연산이 많아져서 성능이 저하
선택 정렬 정렬을 위한 교환 횟수가 적어 내림차순된 데이터를 오름차순할 때 효율이 좋음 정렬 비교 횟수가 많고, 정렬된 상태서 소수의 자료가 추가되면 재정렬 시 최악의 처리 속도를 보임
삽입 정렬 버블정렬의 비교횟수를 줄이기 위해 고안된 방법이며, 크기가 적은 데이터 집합을 정렬하는 알고리즘을 작성할 때 효율이 좋음 데이터의 상태와 크기에 따라 성능 편차가 큰 정렬 방법
힙 정렬 추가적인 메모리를 필요로하지 않으면서 항상 시간 복잡도 $O(N\times logN)$ 를 가짐 실제 시간을 측정 시 퀵정렬보다 느림. 즉, 데이터의 상태에 따라서 다른 정렬들에 비해 느린편. 안정성을 보장받지 못함
병합 정렬 퀵 정렬과 달리 기준값을 설정하는 과정없이 무조건 절반으로 분할하기에 기준값에 따라 성능이 달라지는 경우가 없음 병합정렬은 임시배열에 원본맵을 계속해서 옮겨주며 정렬을 하는 방식이기에 추가적인 메모리가 필요
퀵 정렬 기준값(Pivot)에 의한 분할을 통해 구현하는 정렬 방법으로, 분할 과정에서 $logN$이라는 시간이 소요되며, 전체적으로 $N\times logN$으로 준수 최악의 기준값을 선택할 경우 $O(N^2)$라는 시간복잡도를 가짐
기수 정렬 $O(N)$이라는 시간복잡도를 가지는 정렬방법으로 매우 빠른 속도를 가짐 버킷이라는 데이터 전체 크기와 기수 테이블의 크기만큼의 추가적인 메모리가 할당돼야 함

 

 

Reference


[1] https://tctt.tistory.com/47

[2] https://yabmoons.tistory.com/250

[3] https://hsp1116.tistory.com/33

[4] https://yaraba.tistory.com/79

 

+ Recent posts