Processing math: 100%

빅오표기법과 시간복잡도

 

1. 정의

- 인수가 특정 값이나 무한으로 향할 때 함수의 극한 행위(limiting behavior)를 표현해주는 수학적 표기 -> 데이터가 늘어날 때 알고리즘 성능이 어떻게 바뀌는가?

- 알고리즘의 효율성을 상한선 기준으로 표기해준다 -> "최악의 시나리오"

 

1.1. 복잡도

 

시간복잡도와 공간복잡도

 

- 시간복잡도 : 입력된 N의 크기에 따라 실행되는 조작의 수 ("데이터 원소가 N개일 때 알고리즘에 몇 단계가 필요한가")

- 공간복잡도 : 알고리즘이 실행될때 사용하는 메모리의 양

 

 

1.2. 수학적 정의

nn0 인 모든 n 에 대해 f(n)cg(n) 인 양수 c, n0 가 존재한다면, f(n)O(g(n)) 이라고 나타낼 수 있다 

 

nO(n)로 나타낼 수 있다 - n0=1, c=1 이면 nn 이 만족되므로 

2nO(n)로 나타낼 수 있다 - n0=1, c=2 이면 2n2n 이 만족되므로 

 

nO(2n)로 나타낼 수 있다- n0=1, c=12 이면 n122n=n 이므로

nO(n2)로 나타낼 수 있다 - n0=1, c=1 이면 nn2 이 만족되므로

 

n2O(n)로 나타낼 수 없다 - c가 아무리 크더라도, 언젠가 항상 cn보다 n2가 커지기 때문에, n2cn 를 만족하는 n0, c가 존재하지 않는다

 

n2O(n2)는 맞음

3n2 역시 O(n2)가 됨

 

....

 

-> 빅오로 시간 복잡도를 표현할때는 최고차항만 표기힌다.

 

 

 

2. 시간복잡도

2.1. 규칙

1. n0

입력값 n은 항상 0보다 크며, 복잡도 또한 0보다 크다고 가정한다

 

2. 함수는 더 많은 입력값이 있을 때 더 많은 작업을 한다

 

3. 모든 상수는 삭제한다

n, 2n, 3n 모두 O(n)으로 표현할 수 있다

 

4. 낮은 차수의 항들은 무시한다

- n 이 무한으로 커지는 경우를 상정한다

- n3+n2+n 에서 시간 복잡도에 영향을 미치는 것은 n3이다

 

5. log의 밑은 무시한다

- 밑은 무시하고 O(logn) 으로 표시한다

 

6. 등호로 표현한다

- 2n=O(n)2nO(n)

 

 

따라서 ...

 

1 O(1) 
2n+20 O(n) 
3n2 O(n2) 

 

이런 식이다.

 

 

2.2. 종류

시간복잡도 1 10 100 문제 해결 단계
O(1) 1 1 1 상수 시간 (문제 해결 시 오직 한 단계만 처리)
O(logn) 0 2 5 로그 시간 (문제 해결에 필요한 단계들이 연산마다 특정 요인에 의해 줄어듦)
O(n) 1 10 100 직선적 시간 (문제를 해결하기 위한 단계의 수와 입력값 n이 1:1 관계를 가짐)
O(nlogn) 0 20 461 선형로그 시간 (문제를 해결하기 위한 단계의 수가  n(log2n) 번만큼의 수행시간을 가짐)
O(n2) 1 100 10000 2차 시간 (문제를 해결하기 위한 단계의 수는 입력값 n의 제곱)
O(2n) 2 1024 1267650600228229401496703205376 지수 시간 (문제를 해결하기 위한 단계의 수는 주어진 상수값 2 의 n 제곱)
O(n!) 1 3628800 표시 불가  

 

 

2.3. 예제

- O(1) : 상수

입력과 관계없이 시간복잡도 동일하게 유지됨

def hello():
    print('hello, world!')

 

- O(N) : 선형

입력이 증가함에 따라 복잡도가 선형적으로 증가함

def print_each(data):
    for item in data:
        print(item)

 

- O(N^2) : Square

반복문이 겹쳐짐

def print_each_n_times(li):
    for n in li:
        for m in n:
            print(n, m)

 

- O(log N), O(N log N)

입력 크기에 따라 처리시간 증가 ex. 정렬알고리즘

# 이진 검색

def binary_search(li, item, first=0, last=None):
    if not last:
        last = len(li)
    midpoint = (last - first) / 2 + first
    if li[midpoint] == item:
        return midpoint
    elif li[midpoint] > item:
        return binary_search(li, item, first, midpoint)
    else:
        return binary_search(li, item, midpoint, last)

 

+ 정렬 알고리즘별, 자료구조별 시간 복잡도..

복사했습니다!