시간복잡도

Computer Science Sep 9, 2025

백준같은 곳에서 알고리즘을 공부하다 보면 필연적으로 시간복잡도라는 개념을 한 번쯤은 보게 된다. 단순히 어떤 알고리즘의 시간복잡도가 \(\mathcal{O}(n^2)\)라는 것을 입력의 크기가 \(n\)일 때 최악의 경우에 실행 시간이 \(n^2\)에 비례한다는 것만 알아도 알고리즘 문제를 푸는 것에는 큰 영향이 없지만, 이 글에서는 시간복잡도의 수학적 정의에 대해서 알아보고자 한다.

시간복잡도를 나타내는 방법은 Big \(\mathcal{O}\), Big \(\theta\), Big \(\Omega\)로 크게 3가지가 있다.

Big $\mathcal{O}$

\[\text{어떤 양의 상수 } M, c\text{과 } M \text{이상의 모든 } x\text{에 대해 } \vert f(x)\vert \le c\vert g(x)\vert\text{일 때 } f(x)\in \mathcal{O}(g(x))\]

보통 위의 정의를 만족할 때 이해하기 쉽도록 \(f(x)=\mathcal{O}(g(x))\)라고 표기하는 경우도 있지만, 여기서는 좀 더 엄밀하게 하기 위해 \(f(x) \in \mathcal{O}(g(x))\)로 표기하도록 하겠다.

점근적 분석과 Big O 표기법. 점근적 분석은 다양한 알고리즘에서 성능을 비교할 때 사용되는… | by 이희랑 | Medium

위 그림에서 보면, \(n\)이 \(n_0\)보다 큰 모든 경우에 \(\vert f(n)\vert \le c\vert g(n)\vert\)이므로 \(f(n) \in \mathcal{O}(g(n))\) 이다.

예를 들어 \(f(x) = x^2\)라고 하자.

만약 \(g(x) = x^3\)이라면 \(c\)가 어떤 양수가 되더라도 충분히 큰 \(M\)가 있어 모든 \(M\)보다 큰 \(x\)에 대해 \(f(x) \le cg(x)\)이므로 \(f(x) \in \mathcal{O}(g(x))\)이다.

만약 \(g(x) = x^2 - 3x\)이라면 \(c\)가 모든 양수는 아니더라도 충분히 큰 \(c, M\)이 있어 \(M\)보다 큰 모든 \(x\)에 대해 \(f(x) \le cg(x)\)이므로 \(f(x) \in \mathcal{O}(g(x))\)이다.

하지만 \(g(x) = x\)이라면 \(c\)가 어떤 수가 되더라도 충분히 큰 \(x\)에 대해 \(f(x) > cg(x)\)이므로 \(f(x) \notin \mathcal{O}(g(x))\)이다.

Big $ \Omega $

\[\text{어떤 양의 상수 } M, c\text{과 } M \text{이상의 모든 } x\text{에 대해 } \vert f(x)\vert \ge cg(x)\text{일 때 } f(x)\in \Omega(g(x))\]

즉, \(Big \mathcal{O}\)와 반대라고 생각하면 편하다.

이번에도 예를 들어 \(f(x) = x^2\)라고 하자.

만약 \(g(x) = x^3\)이라면 \(c\)가 어떤 양수가 되더라도 충분히 큰 \(x\)에 대해 \(\vert f(x)\vert < c\vert g(x)\vert\)이므로 \(f(x) \notin \Omega(g(x))\)이다.

만약 \(g(x) = x^2 - 3x\)이라면 \(c\)가 모든 양수는 아니더라도 충분히 작은 \(c\)와 충분히 큰 \(M\)가 있어 \(M\)보다 큰 모든 \(x\)에 대해 \(\vert f(x)\vert \ge c\vert g(x)\vert\)이므로 \(f(x) \in \Omega(g(x))\)이다.

그리고 \(g(x) = x\)이라면 충분히 큰 \(M\)이 있고 \(c\)가 어떤 양수가 되더라도 충분히 큰 \(x\)에 대해 \(\vert f(x)\vert \ge c\vert g(x)\vert\)이므로 \(f(x) \in \Omega(g(x))\)이다.

Big $\theta$

\[f(x) \in \mathcal{O}(g(x)) \text{이고 } f(x) \in \Omega(g(x)) \text{일 때 } f(x) \in \theta(g(x))\]

사실 Big \(\theta\)는 이게 끝이다.


성질

Big \(\mathcal{O}\), Big \(\Omega\), Big \(\theta\) 표기법에는 여러 성질들이 있다.

1. 반사성

\[f(x) \in \mathcal{O}(f(x)), f(x) \in \Omega(f(x)), f(x) \in \theta(f(x))\]

2. 전이성

\[f(x) \in \mathcal{O}(g(x)), g(x) \in \mathcal{O}(h(x)) \text{이면 } f(x) \in \mathcal{O}(h(x))\]

\[f(x) \in \Omega(g(x)), g(x) \in \Omega(h(x)) \text{이면 } f(x) \in \Omega(h(x))\]

\[f(x) \in \theta(g(x)), g(x) \in \theta(h(x)) \text{이면 } f(x) \in \theta(h(x))\]

3. 대칭성

\[f(x) \in \theta(g(x)) \Leftrightarrow g(x) \in \theta(f(x))\]

4. 전치 대칭성

\[f(x) \in \mathcal{O}(g(x)) \Leftrightarrow g(x) \in \Omega(f(x))\]

5. 덧셈 규칙

위에서 추측할 수 있듯이, \(\mathcal{O}(f(x)), \Omega(f(x)), \theta(f(x))\)는 전부 다 집합이다.

\[\mathcal{O}(f(x)) + \mathcal{O}(g(x)) = \mathcal{O}(f(x) + g(x))\]

\[\Omega(f(x)) + \Omega(g(x)) = \Omega(f(x) + g(x))\]

\[\theta(f(x)) + \theta(g(x)) = \theta(f(x) + g(x))\]

예를 들어 \(\mathcal{O}(x^2) + \mathcal{O}(x) = \mathcal{O}(x^2+x) \text{이고, } \mathcal{O}(x^2+x) = \mathcal{O}(x^2)\)이므로 \(x\)가 충분히 큰 수라고 생각했을 때

\[\mathcal{O}(f(x)) + \mathcal{O}(g(x)) = \mathcal{O}(max(f(x), g(x)))\]

으로 써도 무방하다. 마찬가지로

\[\Omega(f(x)) + \Omega(g(x)) = \Omega(min(f(x), g(x)))\]

도 성립한다.

6. 곱셈 규칙

\[\mathcal{O}(f(x)) \cdot \mathcal{O}(g(x)) = \mathcal{O}(f(x) \cdot g(x))\]

\[\Omega(f(x)) \cdot \Omega(g(x)) = \Omega(f(x) \cdot g(x))\]

\[\theta(f(x)) \cdot \theta(g(x)) = \theta(f(x) \cdot g(x))\]

\(f(x) = x^2, g(x) = log(x)\)라 하자. \(x\)가 충분히 클 때 \(\mathcal{O}(f(x))\)에 속한 함수는 \(f(x)\)보다 작거나 같고, \(\mathcal{O}(g(x))\)에 속하는 함수는 \(g(x)\)보다 작거나 같다. 당연히 이 둘의 곱은 \(\mathcal{O}(f(x) \cdot g(x))\)보다 작거나 같다.

어떤 알고리즘이 좋을까?

잠시 정보과학의 영역으로 넘어와 보자. 알고리즘의 시간복잡도는 알고리즘의 효율성을 따질 때 중요한 지표 중 하나인데, 맨 처음에도 말했듯이 Big \(\mathcal{O}\) 표기법으로 나타낼 수 있다. \(0 < a < b\)인 \(a, b\)가 존재하고 \(x\)가 충분히 클 때, 알고리즘의 시간복잡도 별 걸리는 시간은 아래와 같다.

\[\mathcal{O}(1) < \mathcal{O}((log(x))^a) < \mathcal{O}((log(x))^b) < \mathcal{O}(x^a) < \mathcal{O}(x^b) < \mathcal{O}(a^x) < \mathcal{O}(b^x) < \mathcal{O}(x!)\]

위의 부등식들과 덧셈 규칙, 곱셈 규칙을 잘 결합하면 알고리즘이 얼마나 효율적인 것인지 알 수 있을 것이다.

결론

처음에는 수학적으로 엄밀하게 시간복잡도를 정의하고 그의 성질들도 엄밀하게 설명하려 했지만, 글을 써내려 갈수록 어쩔 수 없이 직관을 요하는 부분이 많았던 것도 사실이다. 이 점은 독자의 양해를 바란다. 이 글을 다 읽었다면 앞으로는 Big \(\mathcal{O}\) 표기법이 나와도 두려워 할 것 없다. 그러니 여러 알고리즘들을 배울 때 시간복잡도 표기가 나오면 위의 정의와 성질들을 곱씹으며 그것이 무엇을 의미하는지 확실히 이해하기를 바란다.

Tags

Choi Changhwan

코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러 코딩시러