하나의 문제를 해결하는 데 알고리즘은 다양할 수 있다. 아래의 예시를 보자.
1부터 n까지의 합을 구하는 알고리즘을 만들어라 (n은 1보다 크거나 같다)
public int getSum(int num) {
int total = 0;
for (int i = 1; i <= num; i++) {
total += i;
}
return total;
}
public static int getSum2(int num) {
int total = num * (num + 1) / 2;
return total;
}
왠지 아래의 알고리즘이 더 빠를 것 같다. 반복문을 사용하지도 않고 공식에 n값을 대입하기만 하면 되니까. 변수도 위에서는 2번, 아래에서는 1번 선언하니까 메모리도 조금 사용하고...
이런 걸 정량화해서 비교하는 방법이 바로 알고리즘 성능 평가다.
요즘 우리가 사용하는 전자 기기들의 저장 공간이 커짐에 따라서 공간 복잡도보다는 시간 복잡도가 알고리즘 평가에 더 중요한 기준이 된다고 한다. 물론, 빅데이터처럼 엄청나게 많은 데이터를 다루는 경우에는 공간 복잡도도 중요하겠지만.
그리고 대체로 시간 복잡도와 공간 복잡도는 반비례하는 경향이 있다.
우선, 이번 글에서는 "시간 복잡도"를 기준으로 정리해보자.
"대략 이게 빠를 것 같네"라고 하지 않고, 정확하게 어느 정도 빠를 것 같은지는 어떻게 알 수 있을까? 다음과 같은 성능 표기법을 사용해서 알고리즘의 대략적인 실행 시간을 표시할 수 있다. N번 실행할 때의 시간 복잡도를 다음의 3가지 방법으로 나타낼 수 있다.
O(1) < O(logn) < O(n) < O(nlogn) < o(n²) < O(2n) < O(n!)
if (n < 10) {
System.out.println("10보다 작습니다");
}
for (int i = 1; i < 3; i++) {
System.out.println(n);
}
for (int i = 1; i < 3; i++) {
for (int j = 1; j < n; j++) {
// 중략
}
}
for (int i = 1; i < n; i++) {
for (int j = 1; j < n; j++) {
// 중략
}
}
그럼 앞에서 1부터 n까지 더하는 알고리즘 예시를 다시 살펴보자.
public int getSum(int num) {
int total = 0;
for (int i = 1; i <= num; i++) {
total += i;
}
return total;
}
public static int getSum2(int num) {
int total = num * (num + 1) / 2;
return total;
}
시간 복잡도 측면에서 아래의 알고리즘이 더 우수하다고 볼 수 있겠다!
오... 뭔가 굉장히 유식하게 알고리즘을 평가할 수 있게 되었다. 🤓