문제

https://school.programmers.co.kr/learn/courses/30/lessons/77884?language=javascript 

 

입출력

 


코드

function solution(left, right) {
    let answer = 0; 
    // left 부터 right 까지의 수들의 약수 개수 구하기
    for(let i = left; i <= right; i++){
        let count = 0; // i의 약수 개수를 저장
        
        // j는 1부터 i의 제곱근까지의 수
        // j가 i의 약수인지 확인
        for(let j = 1; j <= Math.sqrt(i); j++){
            if(i % j === 0) { // i가 j로 나누어 떨어지면 약수이다.
                count++;
                if(i / j != j) count++; // i = 25, j = 5의 경우 5를 2번 세면 안됨.
            }
        }
        // 약수의 개수가 짝수면 더하고 홀수면 빼기
        count % 2 === 0 ? answer += i : answer -= i;
    }
    return answer;
}

 

풀이

left와 right 사이에 있는 수들의 약수 개수를 구하고, 그 개수가 짝수면 더하고 홀수면 빼면 된다.

 

1. 반복문으로 left에서 right까지 돌면서 i의 약수 개수를 구해준다. count는 i의 약수 개수를 저장할 변수이다.

2. j를 1부터 i의 제곱근까지 확인하면서 i의 약수인지 확인하고, i가 j로 나누어 떨어지면 약수이므로 count++ 해준다.

이때, i의 끝까지 확인하는 것이 아니라 i의 제곱근까지만 확인하는 이유는 굳이 끝까지 확인하지 않아도 되기 때문이다. 물론 다 확인해서 약수를 구해도 답을 구할 수 있다.

 

예를 들어, i = 25라고 해보자.

25의 약수는 1 5 25 이다.

 

방법 1) 1부터 끝까지 확인하는 방법

1부터 25까지 돌면서 25 % 1 === 0 , 25 % 2 === 0, ... 25 % 25 === 0 을 확인해 count++를 해준다.

-> 3개가 나온다.

 

방법 2) 1부터 i의 제곱근인 5까지 확인하는 방법(에라토스테네스의 체)

25 % 1 === 0, 25 % 2 === 0, 25 % 3 === 0, 25 % 4 === 0, 25 % 5 === 0 을 확인한다.

나누어 떨어진다면 i의 약수이다. 그러나 제곱근까지만 확인했기 때문에 count를 한 번 더 세주어야한다. 1 x 25 = 25이므로, 1도 25의 약수이고 25도 25의 약수가 된다. 따라서 1을 세줄 때, 25도 같이 세어주어야한다.

5가 약수인지 판단했을 때, 25 % 5 는 0이어서 약수로 판명이 된다. 

이때 5의 경우에는 한 번만 세주어야 하므로(5 x 5 = 25), i / 5 == 5 인 경우에는 세어주면 안된다.

따라서 i / j != j 인 경우에만 count를 한 번 더 세어주었다. i != j * j 와 같은 식이다.

 

구한 i의 약수의 개수가 짝수면 answer에 더해주고, 홀수면 빼주었다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90

프로그래머스에서 하루에 level 0 문제를 4개씩 25일간 풀면 머쓱이 스탬프를 준다. (+ 다른 사람의 답을 보면 안된다.)

 

SSAFY에서 자바로만 코딩테스트 공부를 하다보니, js를 까먹을 것 같아서 하루에 4문제씩 js로 풀었다. 덕분에 깃헙 잔디 심기도 다시 시작했다.

 

비록 어려운 문제는 아니지만 바쁜 와중에도 꾸준히 풀었다는 것이 뿌듯하다!

앞으로는 level1 문제들을 차근차근 풀어가고 싶다 🙂

 

25일간 열심히 푼 문제들.

728x90

문제

https://school.programmers.co.kr/learn/courses/30/lessons/42748

 

코드

function solution(array, commands) {
    const answer = []; // 결과를 저장할 배열

        // commands 를 돌며 각 경우의 값을 구한다.
    for(let i = 0; i < commands.length; i++){
        const arr = array.slice(commands[i][0]-1, commands[i][1]).sort((a,b)=>a-b);
        answer.push(arr[commands[i][2]-1]);
    }

    return answer;
}

 

해설

입력으로 들어오는 array를 조건에 맞게 잘라 원하는 인덱스의 값을 반환하는 문제이다.

js의 Array.prototype.slice() 를 이용하면 쉽게 구할 수 있다.

command[i][0]-1은 begin, command[i][1]은 end가 된다. 배열은 0번째 인덱스 부터 시작하지만, 문제에서는 1부터 시작이기 때문에, 배열의 인덱스로 맞추어 주려면 1을 빼주어야한다.

 

command[i][1]의 경우는 1을 빼주지 않아도 된다. 왜냐하면 slice 함수는 end-1 인덱스 까지 잘라주기 때문이다.

그 후 sort 함수를 이용해서 자른 배열을 정렬시켜주었다. 람다 함수를 이용해서 오름차순 정렬을 해주었는데, 따로 정렬 조건을 부여하지 않으면 원하는 대로 정렬이 되지 않을 수 있다.

 

js는 오름차순 정렬을 위해 그냥 sort() 만 사용하면 [10,9]를 정렬할 경우 [10,9] 로 정렬이된다. 원하는 결과인 [9,10] 과 다르게 나온다. 그 이유는 처음 앞 숫자인 1과 9를 비교했을 때 9가 크기 때문이다. 따라서 원하는 대로 정렬을 하려면 정렬 조건을 부여해주는 것이 좋다.

 

정렬이 완료되었다면, command[i][2]번째 인덱스를 구헤야한다. 그러나 위에서 말했듯이, 문제에서는 1부터 시작하지만 배열은 0번째 인덱스부터 시작하므로 우리가 만든 배열에 대입하기 위해서는 1을 빼주어야한다.


* Array.prototype.slice()

배열명.slice([begin[, end]])

배열의 begin 인덱스부터 end-1 인덱스까지 잘라서 반환한다.

const arr = [1,2,3,4,5]

// begin & end를 모두 입력받는 경우
// begin 부터 end-1 인덱스까지 잘라 반환
console.log(arr.slice(1,3)) // [2,3]

// begin 만 입력 받는 경우
// array[begin]부터 array의 끝까지 잘라 반환
console.log(arr.slice(3)) // [3,4,5]

// 아무것도 입력하지 않는 경우
// array 그대로 반환
console.log(arr.slice()) // [1,2,3,4,5]

 

* Array.prototype.sort()

배열명.sort([compareFunction])

const arr = [8,9,10]

// sort()만 사용하는 경우
console.log(arr.sort()) // [10,8,9]

// 오름차순 정렬
console.log(arr.sort((a,b)=>a-b)) // [8,9,10]

// 내림차순 정렬
console.log(arr.sort((a,b)=>b-a)) // [10,9,8]
728x90

+ Recent posts