
근데 약수를 어떻게 구하지? for문 돌려야하나?...
예전에 for문 넣었다가 복잡도가 나와버려서 왠지 하기 싫지만 방법이 떠오르지 않음으로 일단 만들어야겠다.
function sol0(left, right) {
var answer = 0;
for (let i = left ; i <= right ; i++ ){
var divisor = -1
for ( let j = 1 ; j < i ; j++){
if (i%j === 0) {
divisor *= -1
}
}
answer += i*divisor
}
return answer;
}
내가 짠 코드의 시간 복잡도를 계산해보자
for문안에 n짜리 for문이 있으니 일 것이다.
// 다른 사람의 풀이 1
function sol1(left, right) {
var answer = 0;
for (let i = left; i <= right; i++) {
if (Number.isInteger(Math.sqrt(i))) {
answer -= i;
} else {
answer += i;
}
}
return answer;
}
제곱근이 정수면 약수의 갯수가 홀수인것을 이용한 방법이다.
시간 복잡도가 N일테니 무조건 나보다 빠를 것이다.
참조 : [노트] 모든 약수를 구하는 알고리즘은 O(sqrt(n))이다.
// 다른 사람의 풀이 2
function sol2(left, right) {
let sum = (left+right)/2*(right-left+1);
let l = Math.ceil(Math.sqrt(left));
while (l**2 <= right) sum -= (l++**2)*2
return sum
}
sum 우선 모든 수를 더한다.
l 제곱근중 가장 작은 정수를 찾는다.
while l을 증가시켜가며 2배값을 뺀다(홀수인 수가 이미 더해져있기때문에)
속도는 1,2 > 0 일 것이다. 시간 복잡도에서 한 차원의 차이가 나서 어쩔 수 없을 것이다.
그리고 오늘의 속도 비교에서는 두가지를 볼것이다.
아래와 같은 방식으로 진행하였다.
// 솔루션0
function sol0(left, right) {
var answer = 0;
for (let i = left; i <= right; i++) {
var divisor = -1;
for (let j = 1; j < i; j++) {
if (i % j === 0) {
divisor *= -1;
}
}
answer += i * divisor;
}
return answer;
}
// 솔루션1
function sol1(left, right) {
var answer = 0;
for (let i = left; i <= right; i++) {
if (Number.isInteger(Math.sqrt(i))) {
answer -= i;
} else {
answer += i;
}
}
return answer;
}
// 솔루션2
function sol2(left, right) {
let sum = ((left + right) / 2) * (right - left + 1);
let l = Math.ceil(Math.sqrt(left));
while (l ** 2 <= right) sum -= (l++) ** 2 * 2;
return sum;
}
//////////////////////////////////////////////////////////
async function runSolutionWithTiming(solutionFn, a, b) {
const startTime = new Date();
for (let i = 0; i < 10000000; i++) {
await solutionFn(a, b);
}
const endTime = new Date();
const executionTime = endTime - startTime;
console.log(`${solutionFn.name} 실행 시간: ${executionTime}ms`);
}
async function main() {
const a = 1;
const b = 10;
await runSolutionWithTiming(sol0, a, b);
await runSolutionWithTiming(sol1, a, b);
await runSolutionWithTiming(sol2, a, b);
}
main()
.then(() => {
console.log("모든 실행이 완료되었습니다.");
})
.catch((error) => {
console.error("에러 발생:", error);
});

1천만회 / 10자리

1만회 / 10자리
너무 짧게 줄어들었다. 반복횟수는 그때그때 조절해야겠다.

100만회 / 10자리
반복 횟수를 0하나 떼니까 정직하게 작동시간도 0하나가 빠졌다.
이하 작동의 결과는 한번에 정리해서 보여주겠다.