Time Complexity
알고리듬의 수행시간을 '이론적으로' 분석
-> 실제로 수행해보고 시간을 측정하는 게 아니다
실제 수행시간은 환경에 따라 달라진다.
- 무슨 코드로 작성했는가?
- 컴파일러 버전은 무엇인가?
- 알고리즘을 수행하는 기계의 스펙은 어떻게 되는가?
- 입력으로 주어지는 데이터의 크기
- 다른 프로세스가 점유한 자원은 얼마나 되는가?
- etc.
-> 이런 모든 환경적 요인들은 고정되었다고(모두 같다고) 가정한다.
추상화
환경적 요인의 조합은 거의 무한
-> 매번 모든 알고리즘을 구현할 수는 없다.
통상적인 어떤 환경에서 알고리즘 A가 알고리즘 B보다 빨랐다면 다른 환경에서도 그렇지 않을까?
-> 환경적 요인을 고려할 필요가 없다: 추상화
Ex) C로 짰든 Java로 짰든 Python으로 짰든 Bubble sort는 다 같은 Bubble sort
알고리즘은 추상적 개념이고 어떻게 기술하냐에 따라 C 함수일 수도 있고 Java method일 수도 있는 것
n에 대한 함수
시간복잡도는 n에 대한 함수, 수행되는 기본 연산의 개수
알고리즘의 수행시간은 수행되는 기본 연산의 개수에 비례할 것
-> n에 대한 증가함수
시간 복잡도 분석
n에 대한 함수 f(n)
분기문(Ex: if)이 많아지면 정확한 f(n)을 알기가 어렵다
-> 근사화/단순화된 case에 대해 분석
ⓐ Best-case Analysis
ⓑ Worst-case Analysis
ⓒ Average-case Analysis
Best-case Analysis: 별 의미 없어서 잘 안 함
최선의 경우에 1초 걸린다 -> ?
Worst-case Analysis: 최악의 경우에 1분이 걸린다
= 어떤 입력이 주어지든 간에 1분 안에는 끝난다
-> 상한
Ex) Selection sort
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void selectionSort(int A[], int n) {
for (int i = 0; i < n - 1; i++) {
int indexMin = i;
for (int j = i + 1; i < n; j++) {
if (A[j] < A[indexMin])
indexMin = j;
}
int temp = A[indexMin];
A[indexMin] = A[i];
A[i] = temp;
}
}
|
cs |
* 초기화 연산은 기본 연산 개수에서 제외
2행: 3개
< − ++
5행: 2개 (초기화 부분의 + 연산은 좀 애매함)
< ++
6행: 3개
[](Indexing operation) <
7행: 1개 (6행 조건이 참일 때만)
=
=> 6~7행: 3~4개
9행 ~ 11행: 6
[]
[] = []
[] =
수행되는 연산의 개수는 6
반복문에서 연산의 개수를 셀 때는 안쪽 반복문부터
안쪽 for문(5~8행)
반복 할 때마다 5~6회 -> 최악의 경우는 "6회"
i+1 n -> 반복 횟수는 (n−i)번. i는 바깥쪽 for문에서 정해짐
바깥쪽 for 문
2행: 3회
안쪽 for문: 6회
9~11행: 6회
-> n−2∑i=0{6(n−i)+10}=3n2+13n−16
가 시간복잡도 (n에 대한 함수)
여기에 환경적인 요인에 따른 비례상수가 붙음
Big-O Notation
그냥 시간복잡도를 나타내기에 적절하니까 쓰는 것일 뿐 시간복잡도와 별개임
(둘은 아예 다른 개념으로 시간복잡도가 없어도 빅오표기법은 있음)
원래는 그냥 두 함수의 관계를 나타내기 위한 표기법
여기서는 함수의 증가속도를 비교하기 위한 표기법
f(n)=O(g(n)) (f(n)≤O(g(n))와 일맥상통)
함수 f의 증가속도가 g보다 빠르지 않다(= 비슷하거나 느리다)
Ex)3n2+13n−16=O(n2)
f(n)=Ω(g(n)) (f(n)≥Ω(g(n))와 일맥상통)
함수 f의 증가속도가 g보다 느리지 않다(= 비슷하거나 빠르다)
Ex)3n2+13n−16=O(n2)
f(n)=Θ(g(n))
함수 f의 증가속도가 g와 비슷하다
증가속도
n→∞일 때 어느 함수가 더 빨리 증가하는가?
= n이 작을 때는 무시

사진에서 표시된 부분은 저렇게 나타낼 수 있다.
극한에 의한 정의
f(n)=O(g(n))(f(n) \leq O(g(n)$)
limn→∞g(n)f(n)>0일 때
무한대로 발산: g(n)의 증가속도가 훨씬 빠름을 의미
양수로 수렴:
f(n)=Ω(g(n)) (f(n)≥Ω(g(n))
limn→∞f(n)g(n)>0일 때
무한대로 발산: g(n)의 증가속도가 훨씬 빠름을 의미
양수로 수렴:
f(n)=Θ(g(n))
f(n)=O(g(n)) 이고 f(n)=Ω(g(n)) 일 때
limn→∞f(n)g(n)이 0이 아닌 양수로 수렴할 때
Ex) f(n)=3n2+3n−16
f(n)=O(n): 틀림
f(n)=O(n2), f(n)=O(n3), f(n)=O(n100): 맞음
∵
f(n) = O(n^3)같은 건 별 의미는 없지만 '틀린' 표현은 아님
f(n) = \Omega(n), f(n) = \Omega(n^2): 맞음
f(n) = \Omega(n^3), f(n) = \Omega(n^{100}): 틀림
\because \; f(n) \geq O(g(n)
f(n) = \Theta(n^2): 맞음
f(n) = \Theta(n), f(n) = \Theta(n^3), f(n) = \Theta(n^{100}): 틀림
f(n) = O(12n^2+3n): 맞음
f(n) = \Omega(972n - 10): 맞음
f(n) = \Theta(0.2n^2)
헷갈릴 때는 극한으로 계산해보면 됨
증가속도에 따른 함수의 서열
① 1 \lt \lt \log n
② \lt \lt \lt n \lt n\log n \lt n^2 \lt n^3
③ \lt \lt \lt 2^n
④ \lt \lt n! \lt n^n
① Poly-logarithm
물론 1과 \log{n} 사이에도 무수히 많은 함수가 있다.
근데 \log({\log{n}}), \log{(\log({\log{n}}))},\;\cdots 같은 식이라 딱히 의미가..?
이런 걸 Poly-logarithm(\log 함수의 다항식)이라 함
② Polynomial
①과 ② 사이에는 n^{0.5} = \sqrt{n}이나 n^{0.1}같은 게 있음
의외로 n^{0.0001}이 (\log{n})^{1000000}보다 빠르게 증가함
③ Exponential
의외로 2^n보다 1.1^n이 빨리 증가함
교수님피셜) 이래서 복리를 해야 된다
④ 얘네보다 더 빠른 것도 많지만(Ex: 2^{2^{2^{2^n}}}) 제일 빠른 걸 구하는 건 별 의미가 없다
왜 Big-O notation인가?
ⓐ 일단 최악의 경우 = 수행 연산 수의 상한
ⓑ 연산의 갯수를 정확히 세는 건 어려움
ⓒ 추상적인 대상으로써 알고리즘에서는 상수는 덜 중요하다.
기술 언어에 따라 세부 연산이 다르긴 하지만 결국 비슷함
- 세부 연산의 수행속도 차이가 있긴 하지만 환경 요인에 대한 상수로 이해한다.
대부분은 연산의 정확한 개수로 세는 것보다는 'n이 클 때 증가하는 경향이 어떤가?'가 더 중요하다.
-> Big-O notation이 적절한 표기법
1
2
3
4
5
6
7
8
9
10
11
12
13
|
void selectionSort(int A[], int n) {
for (int i = 0; i < n - 1; i++) {
int indexMin = i;
for (int j = i + 1; i < n; j++) {
if (A[j] < A[indexMin])
indexMin = j;
}
int temp = A[indexMin];
A[indexMin] = A[i];
A[i] = temp;
}
}
|
cs |
6~8행의 연산 횟수는 고정임 -> c_1회라고 치자
-> 바로 바깥쪽 for 문이 (n-i)번이니까 c_1(n-i)번
9~11행의 연산 횟수도 고정 -> 바깥쪽 for문 한 번 당 c-2회라고 치자
=> 총 연산 횟수 = \sum^{n-2}_{i=0} c_1(n-i) + c_2 \; = \; O(n^2)
Big-O notation에서는 이런식으로 대략적으로 세면 됨
더 loose하게 하면 안쪽 for문은 최대 n번이고 바깥쪽 for 문이 n번이니까
대충 n \times n 해서 n^2번 -> O(n^2)
'강의노트 > 알고리듬' 카테고리의 다른 글
[알고리듬] 4주차: Divide-and-Conquer (0) | 2021.03.24 |
---|---|
[알고리듬] 3주차: Homework#1 (0) | 2021.03.21 |
[알고리듬] 3주차: Recursion - Mergesort, Quicksort (0) | 2021.03.17 |
[알고리듬] 2주차: 정렬 (0) | 2021.03.15 |
[알고리듬] 1주차 (0) | 2021.03.03 |