정수가 있을 때, 짝수라면 반으로 나누고, 홀수라면 1을 뺀 뒤 반으로 나누면, 마지막엔 1이 됩니다. 예를 들어 10이 있다면 다음과 같은 과정으로 1이 됩니다.
10 / 2 = 5
(5 - 1) / 2 = 4
4 / 2 = 2
2 / 2 = 1
위와 같이 4번의 나누기 연산으로 1이 되었습니다.
정수들이 담긴 리스트 num_list가 주어질 때, num_list의 모든 원소를 1로 만들기 위해서 필요한 나누기 연산의 횟수를 return하도록 solution 함수를 완성해주세요.
3 ≤ num_list의 길이 ≤ 15
1 ≤ num_list의 원소 ≤ 30
num_list | result |
---|---|
[12, 4, 15, 1, 14] | 11 |
입출력 예 설명
입출력 예 #1
12는 3번, 4는 2번, 15는 3번, 1은 0번, 14는 3번의 연산이 필요하기 때문에 총 11번의 연산이 필요합니다.
function solution(num_list) {
let result = 0;
for(let i = 0; i < num_list.length; i++){
while(num_list[i] > 1){
let num = 0;
if(num_list[i] % 2 === 0){
num = num_list[i] / 2
result += 1
} else {
num = (num_list[i] - 1) / 2
result += 1
}
num_list[i] = num
}
}
return result
}
해당 문제에서 중요하 점은 값이 정수인지 음수인지에 따라 반환하는 값이 다르다는 점이다.
또한 1이 될 때까지 나눠줘야하는데 이점을 봤을 때 while문을 사용하면 되겠다는 생각을 했다.
for문을 이용해 num_list를 순환하고
while문의 조건으로 num_list[i]가 1보다 클 때 까지 순환한다.
나눈 값을 담을 num을 선언해 주고
num_list[i]가 정수 인지, 음수인지에 따라 조건을 다르게 작성해 주었다.
이 때 한 번 연산이 이루어 질 때 마다 result에 1을 더해 줬다.
마지막으로 num_list[i]에 연산된 값으로 재 할당해 주므로써 원하는 값을 얻을 수 있었다.
초반에 num_list[i] = num
연산된 값으로 재 할당하지 않아
num_list[i] > 1
조건이 충족되지 않아 무한 루프에 걸렸었다.
이번 시간에 while에 대해 다시 공부하게 된 것 같다.
function solution(num_list) {
let result = 0;
for(let i = 0; i < num_list.length; i++){
while(num_list[i] > 1){
let num = num_list[i] % 2 === 0 ? num_list[i] / 2 : (num_list[i] - 1) / 2
result += 1
num_list[i] = num
}
}
return result
}
if문 대신 삼항연산자를 사용했다. 삼항연사자는 바로 값이 될 수 있다.
이 점을 이용해 num에 바로 값을 할당했다.
이로서 불필요한 코드를 줄일 수 있었다.
프로그래머스는 forEach, map, filter, reduce 메소드 내부에 다른 변수 등을 넣을 수 없는지 알 수 없다...
이번 문제도 for문 대신 forEach나 map메소드로 작성했다면 좀 더 간결하게 작성할 수 있었을 것 같다.
function solution(num_list) {
return num_list.map(v => v.toString(2).length - 1).reduce((a, c) => a + c);
}
toString()
을 통해 이진수로 만들어서 푸셨다.
이분은 진짜 대단한 것 같다...
function solution(num_list) {
return num_list.reduce((acc, cur) => {
let count = 0;
while (cur !== 1) {
cur = cur % 2 ? (cur - 1) / 2 : cur / 2;
count++;
}
return acc + count;
}, 0);
}
이분은 reduce로 작성하셔서 가지고 왔다.
코드 보는 눈을 많이 길러야겠다.