알고리즘의 성능을 나타내는 척도
복잡도는 시간 복잡도(Time Complexity)와 공간 복잡도(Space Complexity)로 나눌 수 있다.
시간 복잡도를 표현할 때는 빅오(Big-O) 표기법을 사용하는데, 최고차 항만 고려하는 표기법이다.
int a = 1;
int b = 2;
System.out.println(a+b); // 3
O(logN) 로그 시간(Log time) :
문제를 해결하는데 필요한 단계들이 연산마다 특정 요인에 의해 줄어듦
# 2의 거듭제곱을 출력하는 함수이다.
# 인풋이 리스트가 아닌 단순 정수이다.
def print_powers_of_two(n):
i = 1
while i < n:
print(i)
i = i * 2
O(N) 선형 시간 : 문제를 해결하기 위한 입력 N 만큼 단계가 필요
int[] array = {3, 5, 2, 1, 4};
int sum = 0;
for(int i = 0; i < array.length; i++) {
sum += array[i];
}
System.out.println(sum);
위 소스코드와 같이 array가 커짐에 따라 비례하여 연산을 수행하는 루프문 부분이므로 시간 복잡도는 O(N)으로 표현할 수 있다.
-> 선형성을 필요로하는 모든 브루트포스 알고리즘은 O(N) 시간 복잡도를 기반으로 한다.
def print_powers_of_two_repeated(y):
for i in range(n): # 반복횟수: n에 비례
j = 1
while j < n: # 반복횟수 : log n에 비례
print(i , j)
j = j * 2
합병 정렬, 퀵 정렬을 예로 들 수 있다. 합병정렬의 분할 단계에서 분할되는 깊이가 logN에 비례한다. 각 깊이별로 분할이 수행되어 합병해야 되는 배열의 수는 많아지지만, 총 원소의 수는 N개로 똑같다.
따라서, 각 깊이별로 수행되는 merge의 시간복잡도는 O(N)이 되며, 이것을 모든 깊이에 대해(logN개만큼) 수행하기 때문에 시간 복잡도는 O(NlogN)으로 표현할 수 있다.
int[] array = {3, 5, 2, 1, 4};
for(int i = 0; i < array.length; i++) {
for(int j = 0; j < array.length; j++) {
System.out.println(a+b);
}
}
위 소스코드와 같이 array 크기만큼 중첩루프를 사용하여 연산 수행하므로 시간 복잡도는 O(N^2)으로 표현할 수 있다.
-> 이 객체들은 O (nlogn) 대응 객체가있을 경우 덜 효율적인 알고리즘으로 간주된다.