ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 거스름돈 Java 풀이
    문제풀이/프로그래머스 2021. 11. 25. 14:16
    반응형

    이 글은 혼자 학습한 내용을 바탕으로 작성되었습니다.

    틀리거나 잘못된 정보가 있을 수 있습니다.

    댓글로 알려주시면 수정하도록 하겠습니다.


    1. 문제

    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 함수를 완성해 주세요.

    2. 입력

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

    3. 예제

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

    4. 풀이

    문제를 풀기 위해 만든 DP 2차원 배열에는 X축은 N까지의 금액이 되며 Y축에는 동전들의 그룹이 나열됩니다.

     

    예제를 DP표로 만들게 되면 위 표와 같이 됩니다.

     

    위 표의 가장 윗줄(빨간색 행)은 해당 행의 동전으로 거스름돈 금액을 거슬러 줄 수 있으면 1을 없으면 0을 입력합니다.

    즉 해당 동전으로 나누어 떨어지면 1을 나누어 떨어지지 않으면 0을 입력합니다.

     

    이유는 해당 동전으로 금액을 만들어지는 경우는 나누어서 떨어지는 경우 1건만 존재하기 때문입니다.

    • 1원을 거슬러 주는 경우는 1원 동전 1개를 거슬러 준 경우 1건입니다.
    • 2원을 거슬러 주는 경우는 1원 동전 2개를 거슬러 준 경우 1건입니다.

     

    첫 줄을 위 과정으로 채워 넣은 결과표는 위와 같습니다.

    ※모든 금액은 1원 동전으로 모두 거슬러 줄 수 있으므로 모두 1이 됩니다.

     

    위 표의 두번째 줄(파란색 행)은 해당 행은 해당 동전보다 금액이 적은 경우와 큰 경우 2가지로 나누어집니다.

    • 동전보다 금액이 적은 경우
      동전보다 금액이 적은 경우는 해당 동전으로 거슬러 줄 수 없는 경우 이므로 이전 동전으로 거슬러 줄 수 있는 경우의 수를 그대로 가지고 옵니다.
      즉 1원의 경우 2원 동전으로 거슬러 줄 수 없으므로 1원 동전으로 거슬러준 경우의 수 1을 그래도 작성합니다.

    • 동전보다 금액이 큰 경우
      동전보다 금액이 큰 경우는 거슬러 주어야 하는 금액의 바로 직전의 동전 경우의 수에 거스름돈 금액에 동전 금액 만큼 뺀 값의 경우수를 더해주면 됩니다.
      즉 3원을 2원 동전으로 거슬러 주는 경우는 1원으로 3원을 만드는 경우의 수 1 + 2원으로 1원을 만드는 경우의 수 1을 더한 2가 정답이 됩니다.

    동전보다 금액이 큰 경우를 추가로 설명 하자면 {1, 2} 동전 그룹으로 3원을 만드는 경우의 수는 2가지 입니다.

    3원에서 가장 뒤에 2원을 추가 하면 5원을 만드는 경우의 수가 됩니다.

    이제 위 2가지 경우에 1원 동전으로 5원을 만드는 경우 1가지를 더하면 총 3가지 경우로 {1, 2} 동전 그룹으로 5원을 만들 수 있습니다.

     

    두번째 줄을 위 과정으로 채워 넣은 결과표는 위와 같습니다.

     

    세번째 줄을 위 과정으로 채워 넣은 결과표는 위와 같습니다.

     

    정답은 DP 2차원 배열의 최하단의 오른쪽 값이 결과 값이 됩니다.

    5. 코드

    전체 코드는 Git에 있습니다.

    int[][] dp = new int[money.length][n + 1];
    for(int i=0; i< money.length; i++)
    	dp[i][0] = 1;
    
    for(int i=1; i<=n; i++)
    	dp[0][i] = i % money[0] == 0 ? 1 : 0;
    
    for(int i=1; i<money.length; i++){
    	for(int j=1; j<=n; j++){
    		if(money[i] <= j)
    			dp[i][j] = dp[i-1][j] + dp[i][j - money[i]];
    		else
    			dp[i][j] = dp[i-1][j];
    	}
    }
    
    return dp[money.length-1][n];
    반응형

    댓글

Designed by Tistory.