[프로그래머스] 레벨3 (level3) 거스름돈

2020년 06월 21일, 09:00

거스름돈

문제설명

Finn은 편의점에서 야간 아르바이트를 하고 있습니다. 야간에 손님이 너무 없어 심심한 Finn은 손님들께 거스름돈을 n 원을 줄 때 방법의 경우의 수를 구하기로 하였습니다.

예를 들어서 손님께 5원을 거슬러 줘야 하고 1원, 2원, 5원이 있다면 다음과 같이 4가지 방법으로 5원을 거슬러 줄 수 있습니다.

1원을 5개 사용해서 거슬러 준다.
1원을 3개 사용하고, 2원을 1개 사용해서 거슬러 준다.
1원을 1개 사용하고, 2원을 2개 사용해서 거슬러 준다.
5원을 1개 사용해서 거슬러 준다.
거슬러 줘야 하는 금액 n과 Finn이 현재 보유하고 있는 돈의 종류 money가 매개변수로 주어질 때, Finn이 n 원을 거슬러 줄 방법의 수를 return 하도록 solution 함수를 완성해 주세요.

제한 사항

  • n은 100,000 이하의 자연수입니다.
  • 화폐 단위는 100종류 이하입니다.
  • 모든 화폐는 무한하게 있다고 가정합니다.
  • 정답이 커질 수 있으니, 1,000,000,007로 나눈 나머지를 return 해주세요.

입출력 예

n money result
5 [1 ,2 ,5] 4

입출력 예 설명

입출력 예 #1
문제의 예시와 같습니다.

문제풀이

  1. dp를 사용하기 위해서 n+1만큼 배열을 만들어준다.(0은 제외시키기 위해서 +1)
  2. dp[0] = 1을 해준다.(0원을 만드는 경우는 모두 가지고 있음).
  3. money만큼 for문을 돌려주는데,
    1. dp가 바뀔 때는, money보다 만들 수 있는 거스름돈이 크거나 같을 때이다. 그래서 i는 항상 el로 시작한다.
    2. 그래서, dp[i] += dp[i-el];을 해준다.(ex. dp[2] = dp[2]+ dp[0] => money가 2일 때 계속 진행하면 2의 배수만 1이 된다.)
function solution(n, money) {
  var answer = 0;
  let dp = Array(n + 1).fill(0);
  dp[0] = 1;
  money.forEach((el, idx) => {
    for (let i = el; i < n + 1; i++) {
      dp[i] += dp[i - el];
    }
  });
  answer = dp[n] % 1000000007;
  return answer;
}

아쉬운 점 || 느낀 점

dp를 이용해서 풀어야한다는 힌트를 얻고도 풀지 못했다.
그냥 진짜 생각이 부족한 것 같다.
생각을 못할 것 같으면 얼른 여러문제들을 풀어보고,
다시 복습해서 경험을 쌓아야 할 것 같다.