시간 복잡도, Big-O(빅오) 표기법

2023년 02월 24일

TOC

Algorithm

온라인 저지, 알고리즘 대회 등에서 문제를 출제할 때 출제자의 의도에 맞는 효율적인 구조로 유도하기 위해 적절한 시간 제한을 두기 때문에, 알고리즘 설계 시 시간 복잡도를 고려하여 작성해야 한다.

알고리즘의 분석 기준

알고리즘의 성능을 분석하는 판단 기준에는 정확성, 명확성, 수행량, 메모리 사용량, 최적성 등이 있다.

정확성 : 자료 입력 시 유한한 시간 내에 올바른 결과를 출력

명확성 : 알고리즘의 표현이 이해하기 쉽고 명확하게 작성

수행량 : 일반적인 연산을 제외하고 알고리즘의 특성을 나타내는 중요 연산을 분석

메모리 사용량 : 명령어, 변수, 입출력 자료와 정보를 저장하기 위한 메모리 사용 정도 판단

최적성 : 사용 환경에 따른 수행량과 메모리 사용량 변화에 대한 최적화를 판단

이러한 기준을 바탕으로 알고리즘을 분석하는 방법에는 실행에 필요한 공간적 측면에서 분석하는 공간 복잡도, 소요 시간 측면의 시간 복잡도가 있다. 이 포스팅에서는 시간 복잡도를 나타내는 Big-O(빅오) 표기법과 간단한 예제들을 다룬다.

Big-O(빅오) 표기법

시간 복잡도 함수에서 불필요한 정보를 제거하여 알고리즘 분석을 쉽게 할 목적으로 시간 복잡도를 표시하는 방법을 Big-O(빅오) 표기법이라고 한다. Big-O에서는 최악의 상황을 가정하여 연산 횟수를 짐작한다.

1️⃣ O(1) : Constant Time

입력 데이터의 크기에 상관없이 일정한 시간이 걸린다면 O(1)의 시간 복잡도를 가진 알고리즘(Constant Time)이라고 한다. 어떤 배열이 있다고 할 경우, 배열의 길이와 상관없이 해당 index에 접근해 즉시 값을 얻을 수 있다.

// C
int arr[3] = {0,1,2};

void printArr(int arr[]) {
    printf("%d\n", arr[0]);
    printf("%d\n", arr[1]);
    printf("%d\n", arr[2]);
}

int main(void) {
    printArr(arr);
}
// Javascript
function printArr(arr, index) {
  return arr[index]
}

const arr = [0, 1, 2]

console.log(printArr(arr, 0))
console.log(printArr(arr, 1))
console.log(printArr(arr, 2))

2️⃣ O(log n) : Logarithmic Time

O(log n)은 로그 복잡도(Logarithmic Time)라고 부르며, Big-O표기법중 O(1) 다음으로 가장 빠르다.
다음 코드는 i = i * 2 에 의해 1, 2, 4, 8, 16 ...인 2의 거듭제곱으로 증가한다. 이는 log2 N번 연산하므로, 시간 복잡도는 O(log n)이다.

// C
void printNum(int n){
    int i = 1;
    while(i < n){
        printf("%d\n", i);
        i = i * 2;
    }
}

int main(void) {
    printNum(20);
}
// Javascript
function printNum(n) {
  let i = 1
  while (i < n) {
    console.log(i)
    i = i * 2
  }
}

printNum(20)

이진 탐색(Binary Search)의 경우 또한 O(log n)의 시간 복잡도를 가진다. 찾고자 하는 값을 정렬된 배열의 중간 값과 비교하여 절반을 탐색 대상에서 제외시키기 때문이다.

bs

3️⃣ O(n) : Linear Time

입력 데이터의 크기에 비례해서 처리시간이 늘어나는 경우 O(n)이다. 입력된 값이 1일 때의 시간이 1초 걸린다면, 입력된 값이 100일 때 100초일 것이다.

// C
void printNum(int n){
    for (int i=0; i < n; i++) {
        printf("%d\n", i);
    }
}

int main(void) {
    printNum(10);
}
// Javascript
const arr = ["a", "b", "c", "d"]

function printArr() {
  for (let i = 0; i < arr.length; i++) {
    console.log(`arr[${i}] = ${arr[i]}`)
  }
}

printArr(10)

4️⃣ O(n log n) : Linearithmic Time

위에서 다룬 O(log n)의 시간복잡도를 가진 while문에 for문이 중첩된 구조이다. for문의 반복횟수는 n에 비례하는 반면, while문의 반복횟수는 log n에 비례한다.

// C
void printNum(int n){
    for(int i=1; i<n; i++){
        int j=1;
        while(j<n){
            printf("%d %d\n",i,j);
            j = j * 2;
        }
    }
}

int main(void) {
    printNum(10);
}
// Javascript
function printNum(n) {
  for (let i = 0; i < n; i++) {
    let j = 1
    while (j < n) {
      console.log(`${i} x ${j} = ${i * j}`)
      j = j * 2
    }
  }
}

printNum(5)

5️⃣ O(n^2) : Quadratic Time

이중 for문을 돌면서 수행하는 알고리즘은 O(n^2)의 시간 복잡도를 갖는다. 입력 데이터가 증가함에 따라 시간이 n의 제곱수의 비율로 증가한다. 2 이상의 제곱이 주어져도 영향력이 미비하기 때문에 통상적으로 O(n^2)으로 표시한다.

// C
void printNum(int n){
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n*2; j++) {
            printf("%d %d\n", i, j);
        }
    }
}

int main(void) {
    printNum(3);
}
// Javascript
function multiplication(n, m) {
  for (let i = 1; i <= n; i++) {
    for (let j = 1; j <= m; j++) {
      console.log(`${i} x ${j} = ${i * j}`)
    }
    console.log()
  }
}

multiplication(9, 9)

6️⃣ O(2n) : Exponential Time

O(2n)은 Big-O(빅오) 표기법 중에서 O(n!)을 제외한다면 가장 느리며, 입력 데이터가 어느 정도 커지면 소요 시간은 무한대에 가까워질 수 있다. 대표적으로 재귀적 수행을 하는 피보나치 수열이 있다.

10870번: 피보나치 수 5 | Baekjoon Online Judge

function fibonacci(input) {
  if (input == 0) return 0
  else if (input == 1) return 1
  else return fibonacci(input - 1) + fibonacci(input - 2)
}
console.log(fibonacci(input))

7️⃣ O(n!) : Factorial Time

Big O 최악의 런타임이다. 입력 데이터의 원소들로 만들 수 있는 모든 순열을 생성한다.
다음 코드는 Factorial Time에 대한 정의이다.

void nFacRuntimeFunc(int n) {
  for(int i=0; i<n; i++) {
    nFacRuntimeFunc(n-1);
  }
}

시간 복잡도 그래프

속도는 O(1) O(log N) O(N) O(N log N) O(N^2) O(2^N) O(N!) 순서대로 빠르다.

bigochart


Reference

Baekjoon Online Judge

Time Complexity and BigO Notation... | by Sebastian De Lima

Big-O Algorithm Complexity Cheat Sheet (Know Thy Complexities!) @ericdrowell

[자료구조] 시간복잡도 with JavaScript

[Algorithm] 시간 복잡도(Time Complexity) - 2WEEKS

알고리즘 복잡도와 빅 오 표기법 :: 비전공 개발자

이진 탐색 (Binary search) 개념 및 구현

[알고리즘] 이분 탐색 / 이진 탐색 (Binary Search)

Written by

yhuj79

🌱 Junior Developer