알고리즘의 효율성 척도에는 알고리즘이 얼마나 빠른지 시간 복잡도만 있는게 아니라 공간 복잡도 또한 존재한다. 즉, 알고리즘이 얼마나 많은 메모리를 소모하는가가 유용할 수 있다.
메모리 제한이 있다면 공간 복잡도가 중요한 요인이다. 대량의 데이터를 다루거나 메모리가 제한된 작은 장치를 프로그래밍할 때는 정말 중요하다.
시간 복잡도를 표현할 때와 마찬가지로 빅 오 표기법을 사용해 공간 복잡도를 표현한다.
공간 복잡도, 메모리 소모 관점에서 핵심 질문은 **“데이터 원소가 N개일 때 알고리즘은 메모리 단위를 얼마나 소모할까?”**이다
function makeUpperCase(array) {
let newArray = [];
for(let i = 0; i < array.length; i++) {
newArray[i] = array[i].toUpperCase();
}
return newArray;
}
이 함수를 공간 복잡도 관점에서 분석하면 원소 N개를 포함하는 새로운 배열을 생성한다. 즉, 원래 배열 이외에 메모리를 더 소모한다.
원소 N개를 추가로 생성했으니 이 함수의 공간 효율성은 O(N)이다.
function makeUpperCase(array) {
for(let i = 0; i < array.length; i++) {
array[i] = array[i].toUpperCase();
}
return array;
}
함수를 이렇게 수정하면 새 배열을 생성하지 않고 원래 배열에서 요소들을 수정하고 수정된 배열을 반환한다. 어떤 메모리도 추가로 소모하지 않는다. 즉, 데이터의 개수에 상관없이 추가로 소모하는 메모리 공간이 0으로 상수이므로, O(1)이다.
버전 | 시간 복잡도 | 공간 복잡도 |
---|---|---|
버전1 | O(N) | O(N) |
버전2 | O(N) | O(1) |
두 버전 모두 시간 복잡도는 O(N)이지만, 두 번째 버전이 O(1)으로 좀 더 메모리가 효율적이다. 속도를 희생하지 않고 공간 관점에서 효율적이므로 버전2의 승리다.
책마다 다르지만, 이 책은 공간 복잡도를 빅 오 표기법으로 나타낼 때 알고리즘에서 새로 생성한 데이터만 고려한다. 예를 들어 위의 예시에서 입력받은 array
가 차지하는 공간은 고려하지 않는다.
알고리즘에서 추가로 소모하는 공간을 보조 공간 auxiliary space이라고 부른다.
다음은 배열을 받아 중복 값이 있는지 확인하고 반환하는 함수다.
// 버전1, 시간 복잡도 O(N²), 공간 복잡도 O(1)
function hasDuplicateValue(array) {
for(let i = 0; i < array.length; i++) {
for(let j = 0; j < array.length; j++) {
if(i !== j && array[i] === array[j]) {
return true;
}
}
}
return false;
}