문제
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 해주세요.
풀이
일단 문제만 보면 반복문을 여러번 돌리면 풀수 있겠다는 생각이 가장 먼저들었지만, 뭔가 시간복잡도가 적은 방법을 고민하다가 시간이 오래걸렸다.
전에가진 배열로 만들어진 경우의 수를 활용하는것 이다.
0 | 1 | 2 | 3 | 4 | 5 | |
1[1] | 1 | 1 | 1 | 1 | 1 | 1 |
2[1,2] | 1 | 1 | 2 | 2 | 3 | 3 |
5[1,2,5] | 1 | 1 | 2 | 2 | 3 | 4 |
1을 이용해서 1,2,3,4,5 를 모두 만들 수 있다.
이렇게 만들어진 상황에서 2가 추가되면 2를 이용해서 2와 4를 하나씩 더만들 수 있다.
같은 이유로 5가 추가되면 5를 만들 수 있기 때문에 답은 4가 된다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
2[2] | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
5[2,5] | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 2 |
하나의 예를 들어 더 설명하면,
2를 이용해서 2, 4, 6, 8, 10 의 경우의 수가 1씩 추가된다. 이경우에서 5가 추가되면,
2와 5를 이용해서 만들 수 있는 수에 모든 경우의 수를 더해주면 된다.
6 은 table[6-1] 을 이용하면 만들어 짐다. 6 = 5 + (1을 만들 수 있는 경우의 수) 가 되기 때문이다.
7 은 table[7-5] 를 이용하면 만들어 진다. 7 = 5 + (2를 만들 수 있는 경우의 수) 가 되기 때문이다.
8 은 table[8-5] 를 이용하면 만들어 진다. 8 = 5 + (3을 만들 수 있는 경우의 수) 가 되기 때문이다.
이와 같은 방식으로 표를 만들어 나가면 된다.
이렇게 하나씩 더해주며 모든 돈을 추가해주면 만들 수 있는 거스름돈의 경우의 수를 뽑아 낼 수 있게 된다.
말로는 쉽지만 이를 코드로 구현해 내는건 쉽지 않다.
for(int i = 0 ; i < money.length ; i++){
for(int j = money[i] ; j <= n ; j++){
sum[j] += sum[j - money[i]];
sum[j] %= 1000000007;
}
}
위 코드가 코드로 구현 한 것이다. 이전까지의 숫자로 만들 수 있는 경우의 수를 더해주면서 경우의 수를 추가 해주면 된다.
<전체코드>
class Solution {
public int solution(int n, int[] money) {
int answer = 0;
int[] sum = new int[n + 1];
sum[0] = 1;
for(int i = 0 ; i < money.length ; i++){
for(int j = money[i] ; j <= n ; j++){
sum[j] += sum[j - money[i]];
sum[j] %= 1000000007;
}
}
answer = sum[n];
return answer;
}
}
'알고리즘 공부 > DP' 카테고리의 다른 글
[프로그래머스] 스티커 모으기(2) (0) | 2021.06.21 |
---|---|
[프로그래머스] 멀리 뛰기 (0) | 2021.06.09 |
[프로그래머스] 등굣길 (0) | 2021.05.23 |
[프로그래머스] 정수 삼각형 (0) | 2021.05.22 |
[프로그래머스] N으로 표현 (0) | 2021.05.17 |