[프로그래머스] 기사단원의 무기 Javascript (lv1)

Taemin Jang·2023년 1월 13일
0

코딩테스트

목록 보기
2/9
post-thumbnail

문제 출처

문제 링크

문제 설명

숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.

각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.

예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.

기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.


제한사항
  • 1 ≤ number ≤ 100,000
  • 2 ≤ limit ≤ 100
  • 1 ≤ powerlimit

입출력 예
number limit power result
5 3 2 10
10 3 2 21

나의 풀이

첫번째 풀이 (실패)

function solution(number, limit, power) {
    // 약수를 저장하는 변수, number+1은 measure[0]은 사용하지 않고 1부터 하기위해
    let measure = Array(number+1).fill(0);
    for(let i = 1; i <= number; i++){
        // 약수의 개수 구하기
        for(let j = 1; j <= i; j++){
            if(i % j === 0){
               measure[i]++;
            }
        }
        // 만약 약수의 개수가 공격력의 제한 수치보다 클 경우 power로 변경
        if(measure[i] > limit) measure[i] = power;
    }
    return measure.reduce((acc,cur) => acc + cur, 0);
}

풀면서 제한사항 최대값이 100,000인 것을 보고 시간복잡도 문제일 것 같았지만, 우선 이중 for문으로 푸는 방법 밖에 생각이 안나서 풀었는데 역시나 시간복잡도에 걸렸다.

소인수분해를 다 해주면 시간복잡도에 걸린다.
이중 for문을 사용해서 시간복잡도는 O(n^2)이다.

약수의 개수는 다 짝이 있지만, 제곱근인 경우는 하나 밖에 없다.

예를 들어 16의 약수는 1, 2, 4, 8, 16 이렇게 있다.
1의 짝은 16, 2의 짝은 8, 제곱근인 4는 짝이 없다.
제곱근을 기준으로 그 전까지 약수가 나오면 짝수를 포함해 2를 카운트 해주고,
제곱근은 1을 카운트 해주면 될 것 같다.
그러면 시간 복잡도도 O(√n*n)이 되어 시간복잡도에 걸리지 않는다.

두번째 풀이 (성공)

function solution(number, limit, power) {
    // 약수를 저장하는 변수, number+1은 measure[0]은 사용하지 않고 1부터 하기위해
    let measure = Array(number+1).fill(0);
    for(let i = 1; i <= number; i++){
        // 약수의 개수는 제곱근을 제외하고 대칭이된다.
        // 따라서 제곱근까지 약수를 구한 후 카운트할 때 제곱근은 1을 더하고 아닌 약수는 2를 더해준다.
        for(let j = 1; j <= Math.sqrt(i); j++){
            if(i % j === 0){
                if(i / j === j) measure[i]++;
                else measure[i] += 2;
            }
        }
        // 만약 약수의 개수가 공격력의 제한 수치보다 클 경우 power로 변경
        if(measure[i] > limit) measure[i] = power;
    }
    return measure.reduce((acc,cur) => acc + cur, 0);
}
profile
하루하루 공부한 내용 기록하기

0개의 댓글