지난주부터 몸풀기로 하루에 한 문제씩 코딩 테스트 연습 문제를 풀고 있다. 간단한 TIL을 매일 노션에 정리하고 있는데 블로그에 공유하고 싶은 내용이 있으면 간간히 포스팅을 해보려고 한다.
문제 설명은 다음의 링크로 갈음한다.
내 풀이
function solution(k, m, score) {
score.sort((a, b) => b - a);
const repeat = parseInt(score.length / m);
let sum = 0;
for (let i = m - 1; i < m * repeat; i += m) {
sum += score[i];
}
return sum * m;
}
입출력 예 #2 로 내가 작성한 코드를 설명해 보겠다.
k = 4,
m = 3,
score = [4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2],
result = 33
접근 방식:
score 배열을 내림차순으로 정렬한 다음, 배열에서 m만큼 끊어주면 한 상자에 담길 사과를 알 수 있다. 상자마다 마지막 요소의 합을 구한 뒤 m을 곱하면 최대 이익을 구할 수 있다.
즉, [4, 4, 4, || 4, 4, 4, || 2, 2, 2, || 2, 1, 1] 에서 파란색으로 표시한 요소의 합 (4+4+2+1) * 3 = 33 이 최종 return 값이다.
1) 변수 repeat : 반복 횟수, 즉 몇 개의 요소를 뽑아서 더할 것인지
2) for loop :
- 초기화: 변수 i는 m-1에서 시작
- 조건문: repeat 횟수만큼 반복
- 증감문: m만큼 증가하면서 반복
반복문 내에서 i는 m-1, m + (m-1), 2m + (m-1), ... , (x-1)m + (m-1)까지 총 repeat번 반복하게 된다.
프로그래머스로 코딩 테스트 연습 문제를 매일 푸는 것 자체도 도움이 되지만 다른 사람의 풀이를 보면서 배우는 게 많다. 다른 사람의 풀이 두 가지를 가져와보겠다.
다른 사람의 풀이 1
solution = (_, m, s) => s.sort().filter((_, i) => !((s.length - i) % m)).reduce((a, v) => a + v, 0) * m
m번째로 잘리는 값을 가져와서 더한 뒤 m을 곱한다는 접근 방식은 나와 동일하지만, 이걸 filter와 reduce 메소드를 써서 한 줄로 끝내버린 풀이법이다.
1) 제한 사항에 3 ≤ k ≤ 9 가 있기 때문에 sort()만으로 오름차순 정렬이 된다. 굳이 sort((a,b) => a-b) 를 해줄 필요가 없었다는 뜻이다.
2) 위의 풀이에서 score.filter((_,i) => !((score.length - i) % m)) 부분이 한 번에 바로 이해가 잘 안됐다. 찬찬히 뜯어보니 나누어 떨어지지 않는 인덱스의 요소는 제거하고, 나머지가 0인 인덱스의 요소만 필터링하는 코드다.
즉, [1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4] 배열이 있을 때 0번째, 3번째, 6번째, 9번째 요소를 뽑는 것이다.
나는 남는 사과를 판별하기 위해서 내림차순 정렬을 한 다음 앞에서부터 끊어가는 방식을 선택했는데, 이 방식으로는 오름차순 정렬로도 충분히 같은 동작을 수행할 수 있다.
다른 사람의 풀이 2
function solution(k, m, score) {
let answer = 0;
const sortedScore = score.slice().sort((a, b) => a - b).slice(score.length % m);
for (let i = 0; i < sortedScore.length; i += m) {
answer += sortedScore[i] * m;
}
return answer;
}
이것도 마찬가지 접근 방식이다. score 배열을 나중에 따로 사용하는 게 아니기 때문에 sortedScore를 구할 때 굳이 .slice()로 복사해서 score를 immutable하게 두지 않아도 되고, sort()만으로도 오름차순 정렬이 된다.
.slice(score.length % m)을 통해서 배열 앞부분의 남는 사과를 버리고 for loop를 돌린 풀이법이다.
코딩 테스트에서 다른 사람의 풀이법을 보면서 재밌는 두 가지 지점이 아예 다른 접근 방식을 볼 때와 똑같은 접근 방식으로 다른 코드를 작성할 때이다. 오늘은 후자의 경우였다. 프로그래밍적인 접근보다 수학적인 접근을 하게 되는 이런 문제를 풀 때면 수학의 정석 예제를 푸는 것 같은 기분이 든다.
'배워서 남 주자' 카테고리의 다른 글
[CSS] 매직 넘버magic number와 상대 단위 em, rem (0) | 2023.05.18 |
---|---|
모바일 기기에서 localhost 접속하는 방법 (2) | 2023.05.15 |
[styled-components] 공통 UI 컴포넌트 및 theme 기능 (2) | 2023.04.06 |
vercel 배포 브랜치 설정 (0) | 2023.03.16 |
[TWIL] 사전 프로젝트를 하며 알게 된 몇 가지 - 최종편 (0) | 2023.03.05 |