빅오의 핵심은 여러가지 코드를 서로 비교하고 성능을 평가하는 방법에 있다.
코드를 분류하거나 비교할 수 있는 시스템에 있어 빅오 표기법이 목적을 갖는다.
// 해결 책 1
// 해결 책 1
function solution1(n) {
let total = 0;
for (let i = 1;i <= n; i++){
total+= i
}
return total;
}
// 대략 time elapsed 141425.35490000597
// 해결 책 2
function solution1(n) {
return n * (n+1)/2
}
// 대략 time elapsed 0.00010000000894069671
let t1 = performance.now()
solution1(1000000000)
let t2 = performance.now()
console.log(`time elapsed ${(t2 - t1) / 1000} sec`)
어떤 게 더 나은 코드인가?
위의 두개의 코드를 속도 측면에서 얼마나 더 좋은지 어떻게 비교할 수 있을까
코드가 실행 될 때 걸리는 정확한 시간을 초로 측정하기 보단 컴퓨터가 처리해야하는 연산 갯수를 세면 된다.
그렇게 되면 알고리즘을 어떤 알고리즘은 실행될 때 연산은 5번 어떤건 7개를 해야한다면 걸리는 시간과 기기엔 변동이 있을 수 있지만 시간은 항상 연산의 갯수에 달려 있을 것이다.
해당 함수의 연산을 세는 방법엔 여러가지가 있지만 간단하게 5n + 2로 표현 가능하다. 하지만 빅오를 볼 땐 이러한 정확한 숫자가 중요한게 아니라 전체적인 추세를 보는 것이다.
N이 커질 수록 연산의 갯수도 시간도 비례적으로 늘어난다는 것을 알 수 있다.
쉽게 말해 f(n)=n은 입력과 실행 시간의 관계를 의미
중요한 건 빅오는 실행시간이 갖을 수 있는 최대치이며
일반적으로 가장 높은 실행 시간 값들을 의미
function solution3(n) {
console.log('up')
for (let i = 0; i< n; i++){
console.log(i)
}
for (let j= n-1; j>=0; j--){
console.log(j)
}
console.log('down')
}
function solution4(n) {
for (let i = 0; i< n; i++){
for (let j= 0; j< n; j++){
console.log(i,j)
}
}
}
모든 연산을 다 세어 정확한 갯수는 중요하지 않으며 전체적인 추세를 중요시한다
5n+2면 단지 n, 단지 추세가 그래프 선이 n의 값과 비례한다는 것
빅오의 복잡도를 분석할 땐 매우 복잡해진다.
1.산수는 상수이며 이는 덧셈, 뺄셈, 곱셈, 나눗셈을 포함 모두 상수 시간에 포함한다.
2. 변수 배정도 상수이다.
3. 인덱스를 사용해서 엘리먼트를 접근하는 것 역시 상수
4. 루프가 있으면 복잡도가 루프의 길이 곱하기, 즉 루프 안에 있는 연산들이 된다.